繁体   English   中英

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

[英]locale Facet Constructor Ignored

locale Facet构造函数

构造其他副本,但从参数facet安装的Facet类型(通常由参数的类型推导)类型除外。 如果facet为NULL,则构造的语言环境是other的完整副本。 以这种方式构造的语言环境没有名称。

我尝试在这里使用Facet进行构造,但是当我在do_decimal_pointdo_thousands_sep放置一个断点时,它们永远不会被称为:(

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

我已经在Visual Studio 2013,Clang 3.6.0和gcc 4.9.2上尝试过此操作。 他们表现得好像我在一个从来没有通过Facet只是用其他locale的行为。

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

编辑:

0x499602D2的请求下,我添加了一个示例。 有趣的是注意的是, Facet似乎确实有所回升,但所用get_money 我正在链接一个实时示例 (必须使用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_sepgrouping 解决方法可能是完全重新实现moneypunct<char>的功能。 我现在正在修补。 同时,我还在这里添加了一个错误: https : //connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information

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

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

  1. moneypunct()
  2. moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)

locale的构造函数调用第二个moneypunct构造函数。 创建适当的_Locinfo是问题的症结所在,因为该信息似乎是特定于实现的。 链接的Visual Studio Bug要求一种无需访问实现细节即可构造功能moneypunct的方法。 代替此信息,必须煮熟所有moneypunct字段。

由于此问题是关于扩展预期的工作moneypunct所以最简单的方法是使用赋值运算符或复制构造函数。 坏消息:这两个都被删除。 因此punct_facet(const money_punct&)将需要在内部编写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 : //stackoverflow.com/a/31454039/2642059

鉴于Visual Studio将v-table指针作为对象布局中的第一项punct_facet ,因此这将导致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 : punct_facet

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM