do_decimal_point и do_thousands_sep не работает

do_decimal_point а также do_thousands_sep кажется, полностью игнорируется моим потоком.

То, что я хочу сделать, это использовать период для моего thousands_sep и запятая для моего decimal_point в get_money. Поэтому я переопределяю moneypunct но это просто игнорируется 🙁

struct punct_facet : public moneypunct<char> {
char_type do_decimal_point() const { return ','; }
char_type do_thousands_sep() const { return '.'; }
};

int main()
{
istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
USCurrency.imbue(locale(locale("en-US"), new punct_facet));
int index = 0;
long double value;

do{
value = 0.0;
USCurrency >> get_money(value, true);
cout << ++index << ": " << value << endl;
} while (value == 123456.0 || value == -123456.0);
return 0;
}

Я ожидаю, что это просто вывод:

1: 123

Но вместо этого я получаю:

1: 123456
2: -123456
3: 123

Что я делаю неправильно? Я использую Visual Studio 2013, в случае, если это может быть очевидно из "en-US",

РЕДАКТИРОВАТЬ:

Я обнаружил, когда я ставлю точку останова в do_decimal_point или же do_thousands_sep что это никогда не ударил. Я не уверен, почему нет, но эта информация, кажется, имеет отношение к проблеме.

0

Решение

Это решение действительно просто объяснение ответ дан здесь.

И конструктор копирования, и оператор присваивания удаляются moneypunct реализация. Что оставляет два плохих варианта для построения punct_facet:

  1. Дублировать все moneypunct члены в punct_facet и позвони всем moneypunct виртуальные функции в punct_facet конструктор для их инициализации. Это имеет очевидный недостаток punct_facet объект в два раза жирнее, чем должен быть, и его конструктор работает дольше, чем это строго необходимо.
  2. Используйте указатели и специфические знания компилятора о компоновке объекта для создания конструкции копирования из moneypunct к punct_facet, Это имеет очевидный недостаток — не быть кроссплатформенным и намеренно игнорировать дизайн стандартной реализации.

Для этого ответа я выбрал плохой вариант 2, потому что реализация moneypunct уже зависит от компилятора для любого аргумента конструкции, кроме: "", "C", или же "POSIX" и потому что есть открытая ошибка против удаленного moneypunct конструктор копирования и оператор присваивания. (Кстати если moneypunct аргумент конструкции корректируется вариант 2 работает в gcc 5.1.0 как хорошо, но это будет не работать в Clang 3.6.0.) Надеемся, что Microsoft вскоре предоставит более функциональный обходной путь для этой ошибки, и нам не придется использовать ни одну из плохих опций.

Так что если 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 конструкторы, и вы получите ожидаемый результат:

123

Чтобы использовать конструктор по умолчанию, вам нужно добавить cout.imdue(locale("en-US")); на вершине main и измени свой imdue заявление для:

USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>()));

Чтобы использовать пользовательский конструктор, вам нужно всего лишь изменить свой imdue заявление для:

USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>(&use_facet<moneypunct<char, true>>(locale("en-US")))));

Конструктор по умолчанию предпочтительнее, так как расхождение между типом шаблона и аргументом конструктора может привести к некоторому плохому поведению.

Одна небольшая нота, ваш USCurrency не использует международный формат валюты, поэтому нет необходимости использовать moneypunct<char, true>, moneypunct<char> будет работать просто отлично. Просто не забудьте изменить его везде как несоответствие между аргументами шаблона punct_facet и аргументы, используемые в get_money снова приведет к неожиданному поведению, которое вы видели.

0

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


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