构造除了从参数facet安装的Facet类型的facet(通常从参数的类型推断出)之外的其他副本。如果facet为NULL,则构造的区域设置是其他区域的完整副本。以这种方式构造的语言环境没有名称。
我尝试使用我的Facet
here进行构建,但是当我在do_decimal_point
和do_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
答案 0 :(得分:0)
事实是,do_decimal_place
尊重do_thousands_place
和get_money
。moneypunct
。困难在于,正在继承的get_money
是默认构建的,因此指导do_decimal_place
调用do_thousands_place
和moneypunct
的支持信息不是建立。
Visual Studio的moneypunct()
实现提供了两个公共构造函数:
moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)
locale
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