c-语言环境Facet构造函数被忽略

locale Facet constructor

Constructs a copy of other except for the facet of type Facet (typically deduced from the type of the argument) which is installed from the argument facet. If facet is NULL, the constructed locale is a full copy of other. The locale constructed in this manner has no name.

我尝试使用Facet here进行构造,但是当我在do_decimal_point和do_thousands_sep中放置一个断点时,它们从不被称为:(

我可以看到Facet传入了,但是它已传入标准库实现文件中,因此我看不到它是否做过任何事情.

我已经在Visual Studio 2013,Clang 3.6.0和gcc 4.9.2上尝试过此操作.他们所有的行为就像我从未使用其他语言环境的行为传递过Facet一样.

我在任何编译器中都找不到针对此构造函数的错误.我想我正在以正确的方式这样做.为什么我无法使用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;
}

输出:

Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.

我希望它能输出:

Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
Hit Foo::do_thousands_sepHit Foo::do_decimal_point

EDIT2:

看来moneypunct< char>不能被继承,因为它不能正确地构造,除非它是由语言环境在内部构造的.至少在Visual Studio上哪个是个问题,因为它通过分组确定是否使用Millennium_Sep.解决方法可能是完全重新实现moneypunct char的功能.我现在正在修补.同时,我还在这里添加了一个错误:https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information

解决方法:

事实是,get_money尊重do_decimal_place和do_thousands_place.困难在于,默认情况下正在构造要继承的moneypunct,因此未设置用于指导get_money调用do_decimal_place和do_thousands_place的支持信息.

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

> moneypunct()
> moneypunct(常量_Locinfo& _Lobj,size_t _Refs = 0,布尔值_Isdef = false)

区域设置的构造函数调用第二个moneypunct构造函数.创建适当的_Locinfo是问题的症结所在,因为该信息似乎是特定于实现的. linked Visual Studio Bug请求一种无需访问实现细节即可构造功能货币点的方法.代替此信息,必须煮熟所有点钱字段.

由于此问题是关于扩展预期的工作点,所以最简单的方法是使用赋值运算符或复制构造函数.坏消息:这两个都被删除.因此,将需要在内部编写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中.我不知道这种育肥的干净解决方法.此处提供编译器特有的技巧:https://*.com/a/31454039/2642059

鉴于Visual Studio将v-table指针作为对象布局中的第一项放置,因此这将导致punct_facet看起来更像这样:

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);
    }
};

顺便说一下,punct_facet的此实现在Clang 3.6.0中不受支持,但在gcc 5.1.0中受支持:http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b

上一篇:javascript – Moment.js的区域设置和特定日期格式


下一篇:linux – UNIX排序忽略空格