locale Facet构造函数被忽略
locale Facet Constructor Ignored
locale
Facet
构造函数:
构造一个other的副本,除了从参数facet安装的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
的行为。
我在任何编译器中都找不到这个构造函数的任何错误。我觉得我这样做是对的。为什么我不能让locale
构建使用我的Facet
?
在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上是一个问题,因为它决定了是否使用grouping
的thousands_sep
。解决方法可能是完全重新实现moneypunct<char>
的功能。我现在正在修补它。同时,我还在这里添加了一个bug: 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(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
。最后,您的类最终看起来像这样:
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
中。我不知道有什么干净的方法可以解决这个问题。这里有一个编译器特定的hack: https://stackoverflow.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
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 使用dynamic_cast和构造函数时出错
- 在c++中使用向量时,如何调用构造函数和析构函数
- locale Facet构造函数被忽略