язык конструктора фасетов игнорируется

locale Facet конструктор:

Создает копию другого объекта, за исключением фасета типа 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

1

Решение

Дело в том, do_decimal_place а также do_thousands_place являются уважаемый get_money, Трудность заключается в том, что moneypunct наследуется от того, что создается по умолчанию, поэтому вспомогательная информация направляется get_money звонить do_decimal_place а также do_thousands_place не настраивается.

Реализация Visual Studio moneypunct предоставляет два открытых конструктора:

  1. moneypunct()
  2. 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

0

Другие решения


По вопросам рекламы [email protected]