[英]locale Facet Constructor Ignored
构造其他副本,但从参数facet安装的Facet类型(通常由参数的类型推导)类型除外。 如果facet为NULL,则构造的语言环境是other的完整副本。 以这种方式构造的语言环境没有名称。
我尝试在这里使用Facet
进行构造,但是当我在do_decimal_point
和do_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_sep
由grouping
。 解决方法可能是完全重新实现moneypunct<char>
的功能。 我现在正在修补。 同时,我还在这里添加了一个错误: https : //connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information
事实是, do_decimal_place
和do_thousands_place
被尊重get_money
。 困难在于,默认情况下正在构造要继承的moneypunct
,因此未设置用于指导get_money
调用do_decimal_place
和do_thousands_place
的支持信息。
Visual Studio的moneypunct
实现提供了两个公共构造函数:
moneypunct()
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.