c++ - locale Facet Constructor Ignored -
constructs copy of other except facet of type facet (typically deduced type of argument) installed argument facet. if facet null, constructed locale full copy of other. locale constructed in manner has no name.
i try construct using facet
here, when put break-point in do_decimal_point
, do_thousands_sep
never called :(
i can see facet
being passed in, it's passed standard library implementation files can't see if ever done it.
i've tried on visual studio 2013, clang 3.6.0, , gcc 4.9.2. all of them behave though had never passed in facet
using other locale
's behavior.
i can't find bugs against constructor in of compilers. think i'm doing right way. why can't locale
construct using facet
?
edit:
at the request of 0x499602d2 have added example. it's interesting note facet
does seem picked not used get_money
. i'm linking live example of this (which useslocale("c")
instead of 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; }
this outputs:
hit foo::do_thousands_sephit foo::do_decimal_point,
.
i expect output:
hit foo::do_thousands_sephit foo::do_decimal_point,
.
hit foo::do_thousands_sephit foo::do_decimal_point
edit2:
it appears moneypunct<char>
can't inherited doesn't constructed properly, unless constructed internally locale
. @ least on visual studio problem because determines whether use thousands_sep
grouping
. work around may reimplement moneypunct<char>
's functionality. i'm tinkering now. in meantime i've added bug here: https://connect.microsoft.com/visualstudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information
the fact is, do_decimal_place
, do_thousands_place
are respected get_money
. difficulty in fact moneypunct
being inherited being default constructed, supporting information direct get_money
call do_decimal_place
, do_thousands_place
not being set up.
visual studio's implementation of moneypunct
provides 2 public constructors:
moneypunct()
moneypunct(const _locinfo& _lobj, size_t _refs = 0, bool _isdef = false)
locale
's constructor calls 2nd moneypunct
constructor. creating proper _locinfo
crux of problem information seems implementation specific. linked visual studio bug requests way construct functional moneypunct
without access implementation details. in lieu of information moneypunct
fields must cooked up.
since question extending expected working moneypunct
easiest way use assignment operator or copy constructor. bad news: both of deleted. punct_facet(const money_punct&)
need written internally implementing behavior of copy constructor. values need copied correspond virtual functions need overridden , punct_facet
. in end class end looking similar this:
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:
this solution cross platform unsatisfactory, because members had added punct_facet
already exist in moneypunct
. not aware of clean workaround fattening. compiler specific hack available here: https://stackoverflow.com/a/31454039/2642059
this result in punct_facet
looked more given visual studio places v-table pointer first item in object layout:
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); } };
incidentally implementation of punct_facet
not supported in clang 3.6.0 is supported in gcc 5.1.0: http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b
Comments
Post a Comment