locale Facet构造函数被忽略

时间:2015-07-08 11:13:37

标签: c++ inheritance locale standards facets

locale Facet constructor

  

构造除了从参数facet安装的Facet类型的facet(通常从参数的类型推断出)之外的其他副本。如果facet为NULL,则构造的区域设置是其他区域的完整副本。以这种方式构造的语言环境没有名称。

我尝试使用我的Facet here进行构建,但是当我在do_decimal_pointdo_thousands_sep中设置断点时,它们永远不会被调用:(

我可以看到Facet被传入,但它被传递到标准库实现文件中,所以我看不出是否有任何事情要做。

我在Visual Studio 2013,Clang 3.6.0和gcc 4.9.2上尝试了这个。 他们的所有表现得好像我从未使用其他Facet行为传递给locale

我在任何编译器中都找不到任何针对此构造函数的错误。我想我正在以正确的方式做到这一点。为什么我无法使用locale构建Facet

修改

the request of 0x499602D2我添加了一个示例。有趣的是,Facet 似乎已被选中,但 get_money一起使用。我正在关联live example of this(必须使用locale("C")代替locale("en-US")):

class Foo : public std::moneypunct<char> {
protected:
    char_type do_decimal_point() const {
        cout << "Hit Foo::do_decimal_point";
        return ',';
    }
    char_type do_thousands_sep() const {
        cout << "Hit Foo::do_thousands_sep";
        return '.';
    }
};

int main()
{
    cout.imbue(locale(locale("en-US"), new Foo));

    const moneypunct<char>* temp = &use_facet<std::moneypunct<char>>(cout.getloc());

    cout << temp->decimal_point() << endl << temp->thousands_sep() << endl;

    istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
    USCurrency.imbue(cout.getloc());

    long double value;

    USCurrency >> get_money(value, true);

    return 0;
}

输出:

  

点击Foo :: do_thousands_sepHit Foo :: do_decimal_point,
  

我希望它输出:

  

点击Foo :: do_thousands_sepHit Foo :: do_decimal_point,
  。
  点击Foo :: do_thousands_sepHit Foo :: do_decimal_point

EDIT2:

moneypunct<char>似乎无法继承,因为它没有正确构造,除非它由locale内部构造。至少在Visual Studio上是一个问题,因为它决定了thousands_sep是否使用grouping。解决方法可能是完全重新实现moneypunct<char>的功能。我现在正在修补它。与此同时,我还在这里添加了一个错误:https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information

1 个答案:

答案 0 :(得分:0)

事实是,do_decimal_place尊重do_thousands_placeget_money moneypunct。困难在于,正在继承的get_money是默认构建的,因此指导do_decimal_place调用do_thousands_placemoneypunct的支持信息不是建立。

Visual Studio的moneypunct()实现提供了两个公共构造函数:

  1. moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)
  2. locale
  3. moneypunct的构造函数调用第二个_Locinfo构造函数。创建一个合适的moneypunct是问题的关键,因为该信息似乎是特定于实现的。 linked Visual Studio Bug请求构建功能moneypunct的方法,而无需访问实现细节。代替这些信息,必须填写所有moneypunct字段。

    由于这个问题是关于扩展预期的工作punct_facet(const money_punct&),最简单的方法是使用赋值运算符或复制构造函数。 坏消息:这两个都被删除了。因此,需要在内部编写punct_facet来实现复制构造函数的行为。需要复制的值对应于需要覆盖的所有虚函数和template <typename T> class punct_facet : public T { protected: typename T::string_type m_grouping; typename T::string_type m_curr_symbol; typename T::string_type m_positive_sign; typename T::string_type m_negative_sign; int m_frac_digits; typename T::pattern m_pos_format; typename T::pattern m_neg_format; typename T::char_type do_decimal_point() const { return typename T::char_type(','); } typename T::char_type do_thousands_sep() const { return typename T::char_type('.'); } typename T::string_type do_grouping() const { return m_grouping; } typename T::string_type do_curr_symbol() const { return m_curr_symbol; } typename T::string_type do_positive_sign() const { return m_positive_sign; } typename T::string_type do_negative_sign() const { return m_negative_sign; } int do_frac_digits() const { return m_frac_digits; } typename T::pattern do_pos_format() const { return m_pos_format; } typename T::pattern do_neg_format() const { return m_neg_format; } public: punct_facet(const T& defaultFacet) : m_grouping(defaultFacet.grouping()), m_curr_symbol(defaultFacet.curr_symbol()), m_positive_sign(defaultFacet.positive_sign()), m_negative_sign(defaultFacet.negative_sign()), m_frac_digits(defaultFacet.frac_digits()), m_pos_format(defaultFacet.pos_format()), m_neg_format(defaultFacet.neg_format()) {} }; 。最后,你的课程最终会看起来像这样:

    punct_facet

    修改

    此解决方案是跨平台的,但也不能令人满意,因为moneypunct中所有必须添加到punct_facet 的成员已经存在。我不知道这种肥胖有一个干净的解决方法。此处提供了编译器特定的hack:https://stackoverflow.com/a/31454039/2642059

    这会导致template <typename T> class punct_facet : public T { private: void Init(const T* money){ const auto vTablePtrSize = sizeof(void*); memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize); } protected: typename T::char_type do_decimal_point() const { return typename T::char_type(','); } typename T::char_type do_thousands_sep() const { return typename T::char_type('.'); } public: punct_facet(){ Init(&use_facet<T>(cout.getloc())); } punct_facet(const T* money){ Init(money); } }; 看起来更像这样,因为Visual Studio将v表指针放在对象布局中的第一项:

    punct_facet

    顺便提一下,Clang 3.6.0不支持 var popit = true; window.onbeforeunload = function() { if(popit == true) { popit = false; return "Are you sure you want to leave?"; } } 的实现,但gcc 5.1.0支持 http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b