Strf allows you not only to add printable types,
but also to override existing ones. The procedure is similar; the
main difference is that instead of defining a PrintableDef type,
you create a facet of the printable_overrider_c<…>
category,
which is almost the same thing.
So this document presumes you already know how to do add printables types.
If you don’t,
click here
to get some explanation.
For example, one could define a facet to override the bool
like this:
struct italian_bool_facet
{
using category = strf::printable_overrider_c_of<bool>;
template <typename CharT, typename Pre, typename FPack>
constexpr static auto make_printer
( strf::tag<CharT>, Pre* pre, const FPack&, bool x ) noexcept
{
return strf::make_printer<CharT>
( pre
, strf::pack()
, strf::unsafe_transcode(x ? "vero" : "falso") );
}
template <typename CharT, typename Pre, typename FPack, typename… T>
constexpr static auto make_printer
( strf::tag<CharT>
, Pre* pre
, const FPack& fp
, strf::value_and_format<T...> x ) noexcept
{
return strf::make_printer<CharT>
( pre
, fp
, strf::unsafe_transcode(x.value() ? "vero" : "falso")
.set_alignment_format(x.get_alignment_format()) );
}
};
Everything in make_printer
( semantics, return type, arguments, etc )
is just like as in the PrintableDef requirements, except that here it is
allowed to be non-static, though it must be then const (
so instead of hardcoded strings like "vero"
, and "falso"
, we could use member variables, which would probably make more sense ).
Just as it is usual in PrintableDef classes,
you can see that we have two make_printer
fuctions.
The second one handles bool
values with formatting.
The format functions that are applicable to a printable
type keep being the same when we override it. We can’t change them.
Defining the format_specifiers
type alias in the overrider facet
has not effect.
Check in the documentation what
are the format functions ( or the FormatSpecifiers )
applicable to the printable type you are overriding.
If you take a look at the part the covers
bool
,
you can see that we only need to handle
alignment formatting.
And that’s what we did in the implementation above.
Things are more lenient regarding facets:
you can completely ignore the facet categories that
influence the original printable type, as well as consider others
or new ones.
You can see that although bool
type is influenced
by lettercase
facet, our override just ignores it.
Anyway, let’s see the result:
auto str = strf::to_string (italian_bool, true, '/', false);
assert(str == "vero/falso");
// and with formatting:
str = strf::to_string
( italian_bool
, strf::center(true, 10, '.'), '/'
, strf::center(false, 10, '.') );
assert(str == "...vero.../..falso...");
Some printable types are not overridable.
A type |
You may be wondering why printable types are overriden this way, i.e. through facets. Couldn’t this library have adoped any of the usual customization point techniques available in C++? Well, the reason it is to avoid the situation where the overriding of a type could be activated by the mere inclusion of a header. After all, headers can be included unintentionally, and you don’t want to accidentaly change how a value is printed.