8

I want to make a operator<< that use the local setings or if not at least manualy be able to change the use of "." for decimal separator to ",". I will like a way of making that the stream (iostream, fstream, etc) to do this and not to create the string and then print it.

Is this possible?

chepner
  • 497,756
  • 71
  • 530
  • 681
user223506
  • 105
  • 1
  • 6

1 Answers1

13

You can imbue a numpunct facet onto your stream. I believe something like this should work for you:

template <typename T>
struct comma_separator : std::numpunct<T>
{
    typename std::numpunct<T>::char_type do_decimal_point() const
    {
        return ',';
    }
};

template <typename T>
std::basic_ostream<T>& comma_sep(std::basic_ostream<T>& os)
{
    os.imbue(std::locale(std::locale(""), new comma_separator<T>));
    return os;
}

int main()
{
    std::cout << comma_sep << 3.14; // 3,14
}

Here is a demo.


A shorter solution, which uses a European locale:

std::cout.imbue(
    std::locale(
        std::cout.getloc(), new std::numpunct_byname<char>("de_DE.utf8")));

But ultimately it depends on the locales that your system provides.

David G
  • 94,763
  • 41
  • 167
  • 253
  • 5
    Wouldn't it be better to use the facet corresponding to the OS locale than to do a custom one like that? – Mark Ransom Jul 17 '13 at 14:38
  • @MarkRansom depends - does not directly answer the question of the OP in that case - what if he's in America and wants to *make us Americans see commas? who knows the true intent – im so confused Jul 17 '13 at 14:39
  • @MarkRansom What code would i change in that case? Would changing `os.getloc()` to `std::locale("")` do it? – David G Jul 17 '13 at 14:42
  • 1
    @0x499602D2 I don't have enough experience with locales to say with 100% certainty but you have some good comments on the question that might help. – Mark Ransom Jul 17 '13 at 14:50
  • *"I want to make a operator<< that use the local setings or if not at least manualy be able to change the use of..."* - Which mentions the user's locale as best solution and the manual use of "," as alternative if that is not possible. So this would indeed *"directly answer the question of the OP"* (while this answer does, too, of course), since we're not answering titles but bodies. – Christian Rau Jul 17 '13 at 15:02
  • I don't understand some comments of this answer. This answer seems to solve the manual method. When I have the chance to check it I mark this answer as the answer of the question. Thanks in any case – user223506 Jul 17 '13 at 15:14
  • 1
    Note this permanently changes the behavior of `std::cout`. If that's not desired, you can create your own `ostream` with `std::ostream custom_out(std::cout.rdbuf());`. Then `custom_out` has its own formatting and locale settings but uses the same output destination as `std::cout`. – aschepler Jul 17 '13 at 15:27
  • @aschepler I know the changes are permanent but I figured that wouldn't be a problem for the OP. – David G Jul 17 '13 at 15:30
  • Not a criticism, just extra info. It isn't clear from the question which behavior is desired. – aschepler Jul 17 '13 at 15:34
  • @user223506 Is there anything you were hoping to see or any functionality that you had in mind that my code sample did not provide? If so, please tell me and I'll try to edit my code accordingly. :) – David G Jul 17 '13 at 23:07