Search code examples
c++fmt

How do I change the formatting of standard types in C++ std::format?


How can I customize the behaviour of std::format so I can get e.g. thousand separators for integer and float types?


Solution

  • The standard format used for standard types, like integers and floating-point types, has an L option to enable locale-specific formatting:

    L (locale-specific formatting)

    The L option causes the locale-specific form to be used. This option is only valid for arithmetic types.

    • For integral types, the locale-specific form inserts the appropriate digit group separator characters according to the context's locale.
    • For floating-point types, the locale-specific form inserts the appropriate digit group and radix separator characters according to the context's locale.
    • For the textual representation of bool, the locale-specific form uses the appropriate string as if obtained with std::numpunct::truename or std::numpunct::falsename.

    For example:

    int intValue = 1000000;
    double dblValue = 1000000.0;
    std::format("{:L} {:L}", intValue, dblValue);
    

    If the user's locale does not define a thousands separator, you can provide your own std::locale that does, eg:

    #include <locale>
    
    class MyNumPunct : public std::numpunct<char>
    {
    protected:
        char do_thousands_sep() const override { return ','; }
        std::string do_grouping() const override { return "\03"; }
    };
    
    ...
    
    std::format(
        std::locale( std::locale(""), new MyNumPunct ),
        "{:L} {:L}", intValue, dblValue
    );
    

    Demo