C++ Logo


Advanced search

Re: [std-proposals] Width Formatting using std::format with custom locale [user defined do_get_separator()]

From: Tam S. B. <cpplearner_at_[hidden]>
Date: Sun, 31 Mar 2024 22:07:49 +0000
This is a MSVC STL bug that got fixed recently. The fix is expected to be shipped in VS 2022 17.10 preview 3.

The PR that fixes the bug is https://github.com/microsoft/STL/pull/4421

From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of David Armour via Std-Proposals <std-proposals_at_[hidden]>
Sent: Sunday, March 31, 2024 9:41
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Cc: David Armour <dave.armour_at_[hidden]>
Subject: [std-proposals] Width Formatting using std::format with custom locale [user defined do_get_separator()]

I encountered an issue using std::format to format numbers which I
wanted to have a custom comma thousand separator in the display.

When using the customised locale with MSVC I discovered the added commas
pushed the formatted number to the right making the number no longer
conform to the width specifier.

I tested the same code with GCC and found std::format() to conform

I also tested both MSVC and GCC using std::cout.imbue() to make the
stream format the numbers to my custom locale. In this instance it
worked correctly on both compilers.

I tried to find some info about this problem and it seems that for
streams, the standard requires the use of std::setw() to include the
custom locale but for std::format it is left to the compiler implementers.

I would suggest that the standard forces the same requirement to manage
the custom locale in the width specifier for std::format as well as for
imbue() on streams.

A code sample that reproduces the problem is found below. As mentioned,
this needs to be compiled on MSVC to see the problem. I have not tested
any other compilers to see if they have the same behaviour as MSVC.

********* CODE BELOW *********
#include <format>
#include <iomanip>
#include <iostream>
#include <locale>

class MyNumPunct : public std::numpunct<char>
   char do_thousands_sep() const override
     return ',';
   std::string do_grouping() const override
     return "\03";

int main()
   double dblValue1 = 1000.0;
   double dblValue2 = 1000000.0;

   // This is used as a ruler to easily see if the formatting is correct.
   std::cout <<
"123456789012345678901234567890123456789012345678901234567890" << std::endl;

   // Standard locale
   std::cout << std::format("{:20.2f}{:20.2f}", dblValue1, dblValue2) <<

   // Custom locale with thousands separator.
   // Error in formatting. Numbers are pushed to the right by the commas.
   std::cout << std::format(std::locale(std::locale(""), new
MyNumPunct), "{:20.2Lf}{:20.2Lf}", dblValue1, dblValue2) << std::endl;

   std::cout.imbue(std::locale(std::locale(""), new MyNumPunct));
   std::cout << std::fixed << std::setprecision(2) << std::setw(20) <<
dblValue1 << std::setw(20) << dblValue2 << std::endl;
   return 0;

******* CODE ENDS *******
Std-Proposals mailing list

Received on 2024-03-31 22:07:53