The C++ Standard Library provides the std::locale class ( used to manage facet object ), as well as the std::numpunct class template. So, why did Strf define its own facets design ( and its own strf::numpunct ) instead of just using what is already well-know and available by the standard ?

To start with, std::locale has the some disadvantages:

These things may be irrelevant in many scenarios, but they are problematic in others. They were probably unavoidable back in the time std::locale was created, but we can do better now with modern C++.

The design of strf::facets_pack class template is similar to as of std::tuple, holding its elements by value, in contrast to std::locale were they are managed through reference counting.

strf::use_facet is as fast as a typical getter: it just returns the reference of the requested object, or, if it is not present, a default value, while std::use_facet probably needs to perform some run-time processing.

There is no base class that facets in Strf need to derive from. They only need to satisfy the Facet type requirements, which is not really demanding. This provides a great flexibility on how a facet can be designed. It can be as simple as an enumeration or as sofisticated as the the charset facets, or the width calculation facets. But one thing all facet of this library have in common is that they all are small and fast to copy, and none of them cause dynamic memory allocation.

strf::numpunct also has some advantages in relation to std::numpunct:

( Be aware that strf::numpunct does not affect bool values, contrary to std::numpunct which has the truename() and falsename() functions. Instead, in Strf there is the print_override_c facet category, which enables you to override how values of bool are printed. )

Furthermore, std::locale and strf::facets_pack have been created with different goals in mind. std::locale is about localization, and it was designed to be used in std::iostream. Strf facets were created to make Strf highly customizable, kind of a complement to format functions. Dealing with numeric punctuation just happens to be one thing they have in common.