2015-07-08 4 views
1

localeFacet constructor:локаль Аспект Конструктор игнорируемого

конструктов копия других для фасета типа Facet (как правило, выведенного из типа аргумента), который установлен с аргументом фаски исключения. Если грань NULL, построенный языковой стандарт является полной копией другого. Таким образом, локаль, построенная таким образом, не имеет имени.

Я пытаюсь построить с помощью моего Facethere, но когда я ставлю брейк-пойнт в моей 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; 
} 

Это выходы:

Hit Foo :: do_thousands_sepHit Foo :: do_decimal_point,
.

Я бы ожидать, что это выход:

Hit Foo :: do_thousands_sepHit Foo :: do_decimal_point,
.
Hit Foo :: do_thousands_sepHit Foo :: do_decimal_point

EDIT2:

Оказывается, что moneypunct<char> не может быть унаследован от, как он не получает построен правильно, если она не будет построена внутренне locale. Что по крайней мере на Visual Studio является проблемой, потому что она определяет, следует ли использовать thousands_sepgrouping. Работа может заключаться в полной переоценке функциональности moneypunct<char>. Теперь я занимаюсь этим.В то же время я также добавил, ошибка здесь: https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information

+0

Не могли бы вы предоставить нам mcve? – 0x499602D2

+0

@ 0x499602D2 Я добавил пример, который, к моему удивлению, аннулирует этот вопрос ... Мне нужно сделать больше исследований о том, как работает 'get_money'. –

+0

Я получаю ожидаемый результат [здесь] (http://coliru.stacked-crooked.com/a/2f0c461fda32a17c). – 0x499602D2

ответ

0

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

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

  1. moneypunct()
  2. moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)

locale «s конструктор вызывает 2-й moneypunct конструктор. Создание надлежащего _Locinfo является основной проблемой, поскольку эта информация, по-видимому, специфична для реализации. linked 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()) {} 
}; 

EDIT:

Это решение кросс-платформенный, но также неудовлетворительна, поскольку все члены, которые должны были быть добавлены к 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, но is поддерживается в gcc 5.1.0: http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b

Смежные вопросы