Создает копию другого объекта, за исключением фасета типа Facet (обычно выводимого из типа аргумента), который устанавливается из фасета аргумента. Если facet равен NULL, созданный языковой стандарт является полной копией другого. Локаль, построенная таким образом, не имеет названия.
Я пытаюсь построить, используя мой 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 является проблемой, потому что он определяет, следует ли использовать 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
конструктор вызывает 2-й moneypunct
конструктор. Создание правильного _Locinfo
Суть проблемы в том, что эта информация зависит от конкретной реализации. связанная ошибка Visual Studio запрашивает способ построения функционала 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
, Я не знаю чистого обходного пути для этого откорма. Хак для конкретного компилятора доступен здесь: https://stackoverflow.com/a/31454039/2642059
Это приведет к punct_facet
это выглядело больше как это, учитывая, что Visual Studio помещает указатель v-таблицы в качестве первого элемента в макете объекта:
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