This document is still a work in progress.

1. facets_pack

1.1. Class template facets_pack

template <typename ... FPE>
class facets_pack;
Compile-time requirements

All types in FPE... satisfy FacetsPackElement.

Member functions

Constructors
constexpr facets_pack(const facets_pack& other) = default;
Effects

Initializes each element in this object with the corresponding element in other

Compile-time requirements

(std::is_copy_constructible_v<FPE> && ...) is true, otherwise this constructor does not participate in overload resolution.

constexpr facets_pack(facets_pack&& other) = default;
Effects

Initializes each element from the rvalue reference of the corresponding element in other

Compile-time requirements

(std::is_move_constructible_v<FPE> && ...) is true, otherwise this constructor does not participate in overload resolution.

constexpr facets_pack() = default;
Effects

Default-initializes each element

Compile-time requirements

(std::is_default_constructible_v<FPE> && ...) is true, otherwise this constructor does not participate in overload resolution.

template <typename... U>
constexpr explicit facets_pack(U&&... u)
Effects

Initializes each element with the correspondig value in std::forward<U>(u)....

Compile-time requirements

This constructor does not participate in overload resolution, unless the following conditions are met

  • sizeof...(U) != 0 is true

  • sizeof...(U) == sizeof...(FPE) is true

  • ( std::is_constructible_v<FPE, U> && ... ) is true

  • if sizeof...(U) == 1 is true, then std::remove_cvref_t<U…​> is not facets_pack<FPE…​.>.

Assignment operators (deleted)
   facets_pack& operator=(const facets_pack&) = delete
   facets_pack& operator=(facets_pack&&) = delete;

Assignments are deleted because it is unclear what would be the correct behavior when there is a reference type in FPE....

1.2. Function template pack

template <typename ... T>
constexpr /* see below */ pack(const T& ... args)
Return type

facets_pack<std::remove_cvref_t<T>>...>

Return value

A facets_pack object initialized with std::forward<T>(args)...

1.3. Function template use_facet

template <typename FCat, typename Tag, typename ... T>
constexpr decltype(auto) use_facet(const facets_pack<T...>& fp);
Effects

If has_facet<FCat, Tag>(fp) returns true then returns <<do_get_facet,do_get_facet<FCat, Tag>(fp), otherwise return FCat::get_default().

Compile-time requirements

FCat is a FacetCategory type.

1.4. Hypothetical function template has_facet

This function template does not exists in this library. It is only documented to help to explain the use_facet function template.
template <typename FCat, typename Tag, typename FPE>
constexpr bool has_facet(const FPE& fpe)
Effects
  • If FPE is an instance of facets_pack, then returns wheter there is any elemente elm in fpe such that has_facet<FCat, Tag>(elm) is true.

  • If FPE is an instance of constrained_fpe<FPE, Filter>, then returns Filter<Tag>::value && has_facet<FCat, Tag>(fpe.get()).

  • If FPE is a Facet type, returns std::is_same_v<FCat, facet_category<FPE>>

Compile-time requirements

1.5. Hypothetical function template do_get_facet

This function template is not part of the library. It is only documented to help to explain the use_facet function template
template <typename FCat, typename Tag, typename FPE>
constexpr decltype(auto) do_get_facet(const FPE& fpe);
Compile-time requirements

1.6. Class template constrained_fpe

template <template <class> class Filter, typename FPE>
class constrained_fpe;

The class template constrained_fpe is designed to be used in facets_pack. constrained_fpe<Filter, FPE> holds a value of FPE that will only be returned by use_facet<Category, Tag> if Filter<Tag>::value is true.

Compile-time requirements

Synopsis

namespace strf {

template <template <class> class Filter, typename FPE>
class constrained_fpe
{
public:
    // constructors
    constexpr constrained_fpe(const constrained_fpe&) = default;
    constexpr constrained_fpe(constrained_fpe&& other) = default;
    constexpr constrained_fpe() = default;

    template <typename U>
    constexpr constrained_fpe(U&&);

    // element access
    constexpr const FPE& get() const;

private:
    FPE element; // exposition only;
};

} // namespace strf

Member functions

Constructors
constexpr constrained_fpe(const constrained_fpe& other);
Effect

Initializes the element of the constrained_fpe from the const reference of the element of other.

Compile-time requirements

std::is_copy_constructible<FPE>::value is true, otherwise this constructor does not participate in overload resolution.

constexpr constrained_fpe(constrained_fpe&& other);
Effect

Initializes the element of the constrained_fpe from the rvalue reference of the element of other.

Compile-time requirements

std::is_move_constructible<FPE>::value is true, otherwise this constructor does not participate in overload resolution.

constexpr constrained_fpe();
Effect

Default-initializes element.

Compile-time requirements

std::is_default_constructible<FPE>::value is true, otherwise this constructor does not participate in overload resolution.

template <typename U>
constexpr explicit constrained_fpe(U&& arg);
Effect

Initializes element with std::forward<U>(arg).

Compile-time requirements

std::is_constructible<FPE, U>::value is true, otherwise this constructor does not participate in overload resolution.

Element access
constexpr const FPE& get() const;
Effect

Return the stored element;

1.7. Function template constrain

template <template <class> class Filter, typename T>
constexpr constrained_fpe<Filter, U> constrain(const T& arg);

constrain is just a syntatic sugar to create a constrained_fpe object.

Return type

constrained_fpe<Filter, U>, where U is std::remove_cv_t<std::remove_reference_t<T>>.

Return value

constrained_fpe<Filter, U>{ std::forward<T>(arg) }

Compile-time requirements

T is such that U satisfies FacetsPackElement.

1.8. Type requirement FacetsPackElement

A given type F satisfies FacetsPackElement if, and only if, one of the following conditions is true:

1.9. Type requirement ConstrainableFacetsPackElement

A given a type F is a ConstrainableFacetsPackElement if, and only if, one of the following conditions is true:

  • F is a Facet type and facet_category<F>::constrainable is true.

  • F is facets_pack<F2...> and all types in F2... are ConstrainableFacetsPackElement.

  • F is an instance of constrained_fpe.

1.10. Type requirement Facet

A given a type F satisfies Facet if all of the following conditions are met:

1.11. Type requirement FacetCagory

A given a type FCat satisfies FacetCategory if:

  • FCat has a static member function named get_default that takes no argument and whose return type is either F or const F&, where F is a type that satisfies the requirements associated to FCat.

  • FCat has a member named constrainable that is a static constexpr value convertible to bool. ( If this value is false then the facets associated FCat can not be constrained ).

1.12. Class template facet_traits

This class template provides the Facet informations. If you create a new facet, you can either define such informations as members of the facet, or specialize facet_traits.

template <typename F>
class facet_traits
{
public:
    using category = /* Facet::category or void */;
};

Public members

typename /* */ category;

Same as Facet::category if such member exist and is a type, otherwise it is an alias to void.

Specialization

template <typename F>
class facet_traits<const F>
{
public:
    using category = typename facet_traits<F>::category;
};

1.13. Type alias facet_category

facet_category is just a syntatic sugar:

template <typename Facet>
using facet_category = facet_traits<Facet>::typename category;

2. Requirements of printable types

This section provides what one needs to be known to add a new printable type or override an existing one.

2.1. Type requirement Printable

A type T is Printable if:

  • print_traits_of<T> is defined and is a PrintTraits type

  • print_traits_of<T>::forwarded_type is implicitly convertible from T

namespace strf {

struct print_traits_tag;

template <typename T> print_traits;

template <typename T> using print_traits_of = /* see below... */;

} // namespace strf

print_traits_of<T> is:

  • print_traits_of<std::remove_cvref<T>>, if T is a reference type or has any cv-qualifier

  • otherwise, it is Traits, when T is value_with_formatters<Traits, /*... */>

  • otherwise, it is print_traits<T> if such template specialization is defined

  • otherwise, it is decltype(tag_invoke(print_traits_tag{}, std::declval<T>()))

2.3. Type requirement PrintTraits

Given

Member types

T::forwarded_type

forwarded_type must be implicitly convertible from P, and must be copy-constructible. And its copy-constructor should be fast. ( forwarded_type is usually P or const P& )

forwarded_type is used intead of P as the storage type in some situations ( for example, the objects created by fmt and join ).

( Optional )
T::override_tag

When defined, global make_printer_input uses the following expression to obtain the PrinterInput object:

use_facet<print_override_c, override_tag>(facets).make_printer_input(…​)

, which would mean that the corresponding Printable type could be overriden by an facet object. While when override_tag is not defined, this Printable type is not overridable.

( Optional )
T::formatters

A type alias to tag<F...>, where all types in F... satisfy Formatter. It affects the return type of fmt.

Member static function templates

Given

  • T, a PrintTraits type.

  • CharT, a character type

  • fpack, a value of type facets_pack</*... */>

  • preview, an lvalue of type print_preview</*... */>

  • v, a value of type T::forwarded_type or value_with_formatters<T, F...>, where F... is such that T::formatters is an alias to tag<F...>.

The following syntax is satisfied:

T::make_printer_input(tag<CharT>{}, preview, fpack, v)
Return type

A PrinterInput type.

Return value

A value r such that &r.preview == &preview

2.4. Type alias template override_tag

namespace strf {

template <typename T>
using override_tag = typename print_traits_of<T>::override_tag;

} // namespace strf

2.5. Variable template is_overridable

namespace strf {

template <typename T>
constexpr bool is_overridable = …​ /*see below*/;

} // namespace strf

is_overridable<T> is true if print_traits_of<T> has the public member type alias override_tag. Otherwise it is false.

2.6. Type alias template forwarded_printable_type

namespace strf {

template <typename T>
using forwarded_printable_type = typename print_traits_of<T>::forwarded_type;

} // namespace strf

2.7. Type requirements PrinterInput

Given

  • CharT, a character type

  • Preview, an instance of the print_preview class template

  • X, a PrinterInput type for types CharT and Preview

  • x, a value of type X

T::char_type

A type alias to CharT.

T::preview_type

A type alias to Preview.

T::printer_type

A type that is constructible from X and convertible to const printer<CharT>&, such that the sequence:

std::size_t s  = x.preview.accumulated_size();
typename T::printer_type p{x};
std::size_t predicted_size = x.preview.accumulated_size() - s;
std::size_t dest_size      = dest.space();
static_cast<const printer<CharT>&>(p).print_to(dest);

statisfies the following postconditions when Preview::size_required is true:

  • if predicted_size <= dest_size is true then dest.recycle() is not called.

x.preview

A lvalue reference of type Preview.

2.8. Class template usual_printer_input

usual_printer_input is a syntactic sugar to create PrinterInput types.

template <typename CharT, typename Preview, typename FPack, typename Arg, typename Printer>
struct usual_printer_input
{
    using char_type = CharT;
    using arg_type = Arg;
    using preview_type = Preview;
    using fpack_type = FPack;
    using printer_type = Printer;

    preview_type& preview;
    FPack facets;
    Arg arg;
};

2.9. Function template make_default_printer_input

namespace strf {

template <typename CharT, typename Preview, typename FPack, typename Arg>
constexpr auto make_default_printer_input
    ( Preview& preview, const FPack& facets, const Arg& arg)
    noexcept(/* see below... */)
    -> /* see below... */

} // namespace strf

The expression make_default_printer_input<CharT>(preview, facets, arg) is equivalent to

print_traits_of<Arg>::make_printer_input(tag<CharT>{}, preview, facets, arg);

This facet category affects the return type and value of global make_printer_input. It enables the user change how a printable type is printed, by making the library use an the alternative PrinterInput object. A facet of this category should aways be constrained to the printable type intended to be overriden.

namespace strf {

struct print_override_c {
    static constexpr bool constrainable = true;

    constexpr static no_print_override get_default() noexcept {
        return {};
    }
};

} // namespace strf

Struct no_print_override

no_print_override is the default facet of print_override_c category.

namespace strf {

struct no_print_override {
    using category = print_override_c;

    template <typename CharT, typename Preview, typename FPack, typename Arg>
    constexpr static auto make_printer_input
        ( tag<CharT>{}, Preview& preview, const FPack& facets, Arg&& arg )
        noexcept(noexcept(make_default_printer_input<CharT>(preview, facets, arg)))
    {
        return make_default_printer_input<CharT>(preview, facets, arg);
    }
};

} // namespace strf

2.11. Function template make_printer_input

namespace strf {

template <typename CharT, typename Preview, typename FPack, typename Arg>
constexpr /*...*/ make_printer_input(Preview& preview, const FPack& facets, const Arg& arg);

} // namespace strf

If print_traits_of<Arg>::override_tag is defined, make_printer_input returns

use_facet< print_override_c
         , typename print_traits_of<Arg>::override_tag >(facets)
    .make_printer_input(tag<CharT>{}, preview, facets, arg);

Otherwise, it returns

print_traits_of<Arg>::make_printer_input(tag<CharT>{}, preview, facets, arg)

2.12. Type alias template printer_type

namespace strf {

template <typename CharT, typename Preview, typename FPack, typename Arg>
using printer_input_type = decltype
    ( make_printer_input<CharT>( std::declval<Preview&>()
                               , std::declval<const FPack&>()
                               , std::declval<Arg>() ) );

template <typename CharT, typename Preview, typename FPack, typename Arg>
using printer_type = typename printer_input_type<CharT, Preview, FPack, Arg>::printer_type;

} // namespace strf

2.13. Class template printer

namespace strf {

template <typename CharT>
class printer {
public:
    using char_type = CharT;
    virtual ~printer() {}
    virtual void print_to(basic_outbuff<CharT>&) const = 0;
};

} // namespace strf
namespace strf {

enum class preview_width: bool { no = false, yes = true };
enum class preview_size : bool { no = false, yes = true };

template <preview_size SizeRequired, preview_width WidthRequired>
class print_preview
    : public size_preview<static_cast<bool>(SizeRequired)>
    , public width_preview<static_cast<bool>(WidthRequired)>
{
public:

    static constexpr bool size_required = static_cast<bool>(SizeRequired);
    static constexpr bool width_required = static_cast<bool>(WidthRequired);
    static constexpr bool nothing_required = ! size_required && ! width_required;
    static constexpr bool something_required = size_required || width_required;

    constexpr print_preview() noexcept = default;
    constexpr explicit print_preview(width_t initial_width) noexcept;
};


using no_print_preview = print_preview<preview_size::no, preview_width::no>;
using print_size_preview  = print_preview<preview_size::yes, preview_width::no>;
using print_width_preview = print_preview<preview_size::no, preview_width::yes>;
using print_size_and_width_preview = print_preview< preview_size::yes
                                                  , preview_width::yes >;

} // namespace strf

Constructors

constexpr print_preview() noexcept;
Effect

Default-construct each of the base classes.

constexpr explicit print_preview(width_t initial_width) noexcept;
Compile-time requirement

WidthRequired is preview_width::yes, otherwise this constructor does not participate in overload resolution.

Effect

Initializes width_preview base with initial_width.

2.15. Class template size_preview

namespace strf {
template <bool Active>
class size_preview
{
public:
    explicit constexpr size_preview() noexcept;
    explicit constexpr size_preview(std::size_t initial_size) noexcept;

    constexpr void add_size(std::size_t) noexcept;
    constexpr std::size_t accumulated_size() const noexcept;
};
} // namespace strf

Member functions

explicit constexpr size_preview() noexcept;
Postcondition

accumulated_size() == 0

explicit constexpr size_preview(std::size_t initial_size) noexcept;
Compile-time requirement

Active is true, otherwise this constructor does not participate in overload resolution.

Postcondition

accumulated_size() == initial_size

constexpr void add_size(std::size_t s) noexcept;
Effects
When Active is false

None

When Active is true

The internally stored size value ( that is returned by accumulated_size() ) is incremented by s.

constexpr void accumulated_size() const noexcept;
Return value
When Active is false

0

When Active is true

The internally stored size value.

2.16. Class template width_preview

namespace strf {
template <bool Active>
class width_preview
{
public:
    constexpr width_preview() noexcept;

    explicit constexpr width_preview(width_t initial_width) noexcept;

    constexpr void subtract_width(width_t) noexcept;

    template <typename IntT>
    constexpr void subtract_width(IntT w) noexcept;

    constexpr void clear_remaining_width() noexcept;

    constexpr width_t remaining_width() const noexcept;
}
} // namespace strf

Member functions

constexpr width_preview() noexcept;
Postcondition

remaining_width() == 0

constexpr width_preview(width_t initial_width) noexcept;
Compile-time requirement

Active is true, otherwise this constructor does not participate in overload resolution.

Postcondition

remaining_width() == initial_width

constexpr void subtract_width(width_t w) noexcept;

template <typename IntT>
constexpr void subtract_width(IntT w) noexcept;
Compile-time requirement

In the template form, std::is_integral<IntT>::value must be true, otherwise it does not participate in overload resolution.

Effects
If (!Active || w <= 0) is true

None

Othersize, if w < remaining_width() is true

The return value of remaining_width is decremented by w.

Otherwise

Equivalent to clear_remaining_width()

constexpr clear_remaining_width() noexcept;
Postcondition

remaining_width() == 0

2.17. Function template preview

template < typename CharT
         , preview_size SizeRequired
         , preview_width WidthRequired
         , typename... FPE
         , typename... Args >
void preview
    ( print_preview<SizeRequired, WidthRequired>& pp
    , const facets_pack<FPE...>& facets
    , const Args&... args );

Calculates the size and/or width of the result of printing the arguments args...

Compile-time requirements
Effects
  • When SizeRequired is preview_size::yes, for each argument arg in args... instantiates the correponding printer type with pp, facets, and arg. This translates into the following expression:

    (..., printer_type< CharT
                      , print_preview<SizeRequired, WidthRequired>
                      , facets_pack<FPE...>
                      , Args >{make_printer_input<CharT>(pp, facets, args)} );
  • When SizeRequired is preview_size::no and WidthRequired is preview_width::yes, for each argument arg in args... instantiates the correponding printer type with pp, facets, and arg ( again, using printer_type and make_printer_input ), while pp.remaining_width() > 0 is true. This implies that not necessarily all argument in arg... are used.

  • When SizeRequired is preview_size::no and WidthRequired is preview_width::no, does nothing

3. Format functions

3.1. Global format functions

namespace strf {
inline namespace format_functions {

constexpr /*…​*/ right {};
constexpr /*…​*/ left {};
constexpr /*…​*/ center {};
constexpr /*…​*/ pad0 {};
constexpr /*…​*/ punct {};
constexpr /*…​*/ hex {};
constexpr /*…​*/ dec {};
constexpr /*…​*/ oct {};
constexpr /*…​*/ bin {};
constexpr /*…​*/ fixed {};
constexpr /*…​*/ sci {};
constexpr /*…​*/ gen {};
constexpr /*…​*/ multi {};
constexpr /*…​*/ conv {};
constexpr /*…​*/ sani {};

} // inline namespace format_functions
} // namespace strf

The format_functions inline namespace contains callable objects that work as alias to format functions

Expression Equivalent Expression

left(arg, width)

fmt(arg) < width

right(arg, width)

fmt(arg) > width

center(arg, width)

fmt(arg) ^ width

left(arg, width, ch)

fmt(arg).fill(ch) < width

right(arg, width, ch)

fmt(arg).fill(ch) > width

center(arg, width, ch)

fmt(arg).fill(ch) ^ width

pad0(arg, count)

fmt(arg).pad0(count)

punct(arg)

fmt(arg).punct()

hex(arg)

fmt(arg).hex()

oct(arg)

fmt(arg).dec()

dec(arg)

fmt(arg).oct()

bin(arg)

fmt(arg).bin()

sci(arg)

fmt(arg).sic()

fixed(arg)

fmt(arg).fixed()

gen(arg)

fmt(arg).gen()

sci(arg, precision)

fmt(arg).sic().p(precision)

fixed(arg, precision)

fmt(arg).fixed().p(precision)

gen(arg, precision)

fmt(arg).gen().p(precision)

multi(arg, count)

fmt(arg).multi(count)

sani(arg, charset)

fmt(arg).sani(charset)

conv(arg, charset)

fmt(arg).conv(charset)

sani(arg)

fmt(arg).sani()

conv(arg)

fmt(arg).conv()

3.2. Callable object fmt

namespace strf {

template <typename T>
using fmt_value_type = typename fmt_type<T>::value_type;

constexpr struct /*…​*/ {
    template <typename T>
    constexpr fmt_type<T> operator()(T&& value) const
        noexcept(noexcept(fmt_type<T>fmt_value_type<T>{(T&&)value}}))
    {
        return fmt_type<T>{fmt_value_type<T>{(T&&)value}};
    }
} fmt;

} // namespace strf

3.3. Type alias template fmt_type

namespace strf {

template <typename T>
using fmt_type = /*…​*/;

} // namespace strf

fmt_type<T> is:

3.4. Class template value_with_formatters

namespace strf {

template <typename ValueType, class... Fmts>
class value_with_formatters;

} // namespace strf
Compile-time requirements
  • All types in Fmt... satisfy Formatter.

  • All types in Fmt... are different.

Synopsis

namespace strf {

template <typename PrintTraits, class... Fmts>
class value_with_formatters
    : public Fmts::template fn<value_with_formatters<ValueType, Fmts...>>...
{
public:
    using traits = PrintTraits;
    using value_type = typename PrintTraits::forwarded_type;

    constexpr explicit value_with_formatters(const value_type& v);

    template <typename... OtherFmts>
    constexpr explicit value_with_formatters
        ( const value_with_formatters<PrintTraits, OtherFmts...>& f );

    template <typename... OtherFmts>
    constexpr explicit value_with_formatters
        ( value_with_formatters<PrintTraits, OtherFmts...>&& f );

    template <typename OtherPrintTraits>
    constexpr value_with_formatters
        ( const value_type& v
        , const value_with_formatters<OtherPrintTraits, Fmts...>& f );

    template <typename OtherPrintTraits>
    constexpr value_with_formatters
        ( const value_type& v
        , value_with_formatters<OtherPrintTraits, Fmts...>&& f );

    template <typename... F, typename... FInit>
    constexpr value_with_formatters
        ( const value_type& v
        , tag<F...>
        , FInit&&... finit );

    template <typename Fmt, typename FmtInit, typename... OtherFmts>
    constexpr value_with_formatters
        ( const value_with_formatters<PrintTraits, OtherFmts...>& f
        , tag<Fmt>
        , FmtInit&& fmt_init );

    constexpr const value_type& value() const;

    constexpr value_type& value();

private:

    value_type value_; // exposition only
};

} // namespace strf
constexpr value_with_formatters(const value_type& v);
Effects
  • Initializes value_ with v

  • Default initializes all public base class subobjects

template <typename... OtherFmts>
constexpr explicit value_with_formatters
    ( const value_with_formatters<PrintTraits, OtherFmts...>& f );
Effects
  • Initializes value_ with f.value()

  • Initializes each public base class subobjects with the corresponding base class subobject of f

template <typename... OtherFmts>
constexpr explicit value_with_formatters
    ( value_with_formatters<PrintTraits, OtherFmts...>&& f );
Effects
  • Initializes value_ with static_cast<value_type&&>(f.value())

  • Initializes each public base class subobjects b with std::move(bf), where bf is the base class subobjects in f that corresponds to b

template <typename OtherPrintTraits>
constexpr value_with_formatters
    ( const value_type& v
    , const value_with_formatters<OtherPrintTraits, Fmts...>& f );
Effects
  • Initializes value_ with v

  • Initializes each public base class subobjects with the corresponding base class subobject of f

template <typename OtherPrintTraits>
constexpr value_with_formatters
    ( const value_type& v
    , value_with_formatters<OtherPrintTraits, Fmts...>&& f );
Effects
  • Initializes value_ with v

  • Initializes each public base class subobjects b with std::move(bf), where bf is the base class subobjects in f that corresponds to b

template <typename... F, typename... FInit>
constexpr value_with_formatters
    ( const value_type& v
    , tag<F...>
    , FInit&&... finit );
Compile-time requirements
  • sizeof...(F) == sizeof...(FInit)

  • There is no repeated type in F...

  • All types in F... are also in Fmts...

Effects
  • Initializes value_ with v

  • For each type in F..., initializes the corresponding public base class subobjects with the corresponging value in std::forward<FInit>(finit)...

  • Default initializes the remaining public base class subobjects

template <typename Fmt, typename FmtInit, typename... OtherFmts>
constexpr value_with_formatters
    ( const value_with_formatters<PrintTraits, OtherFmts...>& f
    , tag<Fmt>
    , FmtInit&& fmt_init );
Compile-time requirements
  • Fmt is one the types in Fmts...

Effects
  • Initializes value_ with f.value()

  • Initializes the public base class subobject that corresponds to Fmt with std::forward<FmtInit>(fmt_init)

  • Initializes the other public base class subobjects with the corresponding base class subobject of f

constexpr const value_type& value() const;
constexpr value_type& value();

Return value_

3.5. Type requirement Formatter

A type Fmt is a Formatter if it has a member fn that is a type template with one template type parameter such that, given any types T and U:

  • Fmt::template fn<T> is well-formed if T is value_with_formatters<ValueType, Fmts...>. In this case, note that Fmt is in Fmts... and T derives from Fmt::template fn<T>.

  • Fmt::template fn<T> is default constructible, assuming it is well-formed.

  • Fmt::template fn<T> can be constructed from const Fmt::template fn<U>&, if both are well-formed.

3.6. Formatter alignment_formatter

The Formatter defines the following format functions:

Format functions Effect

operator<(width_t width)

Aligns to the left ( Or to the right on right-to-left (RTL) scripts, like arabic )

operator>(width_t width)

Aligns to the right ( Or to the left on RTL scripts )

operator^(width_t width)

Center alignment

fill(char32_t ch)

Sets the fill character.

set_alignment_format(alignment_format)

Set all alignment formatting options simultaneously.

set_alignment_format(default_alignment_format)

Set all alignment formatting options to default.

And the following observers:

Observers Return type

width()

width_t

get_alignment_format()

default_text_alignment or text_alignment, depending on whether any alignment format function has been previously invoked.

Enumeration text_alignment

namespace strf {

enum class text_alignment {left, right, center};

}

struct alignment_format

namespace strf {

struct alignment_format {
    char32_t fill = U' ';
    width_t width = 0;
    text_alignment alignment = text_alignment::right;
};

} // namespace strf

struct default_alignment_format

namespace strf {

struct default_alignment_format {
    static constexpr char32_t fill = U' ';
    static constexpr width_t width = 0;
    static constexpr text_alignment alignment = text_alignment::right;

    constexpr operator alignment_format () const noexcept
    {
        return {};
    }
};

} // namespace strf

3.7. Formatter int_formatter

This Formatter defines the following format functions:

Member function Effect

bin()

Uses the binary base.

oct()

Uses the octal base.

dec()

Uses the decimal base.

hex()

Uses the hexadecimal base.

operator*()

Equivalent to the '#' format flag in printf. Only applicable in non-decimal bases.

operator+()

Equivalent to the '+' format flag in printf. Only applicable in decimal base.

operator~()

Equivalent to fill_sign()

fill_sign()

Similar to the ' ' format flag in printf: prints an extra fill character ( specified by some of the alignment format function ) before non-negative numbers. Only applicable in decimal base.

punct()

Applies the numeric punctuation according to the numpunct_c facet

operator!()

Equivalent to punct()

pad0(unsigned w)

Inserts zeros after the sign or base indication and before the digits such that at least w characters are printed ( not counting the fill characters caused by alignment formatting, but still counting the extra fill character caused by fill_sign() ).

p(unsigned precision)

Inserts zeros after the sign or base indication and before the digits such that at least precision digits are printed

set_int_format(int_format)

Set all integers formatting options simultaneously.

set_int_format(default_int_format)

Reset all integers formatting options to default.

And the following observer:

Observer Return type

get_int_format()

int_format, default_int_format or an implementation-defined IntFormat type.

Type requirements IntFormat

Given:

  • F, a InttFormat type

  • f, a value of type F

The following must hold:

  • F is copy-constructible

  • F is convertible to int_format

  • F has public member variables below:

Member Type Semantics / effect

f.base

int

Numeric base ( must be euqal to 2, 8, 10 or 16 )

f.precision

unsigned

See p format function.

f.pad0wdith

unsigned

See pad0 format function.

f.sign

showsign

See enumeration showsign

f.showbase

bool

Equivalent to the '#' format flag in printf

f.punctuate

bool

Activates numeric punctuation.

Struct template int_format

namespace strf {

struct int_format {
    int base = 10;
    unsigned precision = 0;
    unsigned pad0width = 0;
    showsign sign = showsign::negative_only;
    bool showbase = false;
};

} // namespace strf

Struct template default_int_format

namespace strf {


struct default_int_format {
    constexpr static int base = 10;
    constexpr static unsigned precision = 0;
    constexpr static unsigned pad0width = 0;
    constexpr static strf::showsign sign = strf::showsign::negative_only;
    constexpr static bool showbase = false;
    constexpr static bool punctuate = false;

    constexpr STRF_HD operator int_format () const
    {
        return {};
    }
};

} // namespace strf

Enumeration showsign

namespace strf {

enum class showsign {
    negative_only = …​, positive_also = …​, fill_instead_of_positive = …​
};

} // namespace strf
showsign::negative_only

A sign is printed only before negative numbers.

showsign::positive_also

Negatives numbers are prefixed with '-' and non-negatives number are prefixed with '+'.

showsign::fill_instead_of_positive

Negatives numbers are prefixed with '-' and non-negatives number are prefixed with the fill character ( from alignment formatting ).

3.8. Formatter float_formatter

The float_formatter Formatter defines the following format functions:

Member function Effect

operator*()

Equivalent to the '#' format flag in printf

operator+()

Equivalent to the '+' format flag in printf

fill_sign()

Similar to the ' ' format flag in printf: prints an extra fill character ( from the alignment formatting ) before non-negative numbers.

operator~()

Equivalent to fill_sign()

punct()

Applies the numeric punctuation according to the numpunct_c facet

operator!()

Equivalent to punct()

pad0(unsigned w)

Similar to the '0' format flag in printf:

For NaN and infinity, causes the the width ( from alignment formatting ) to be at least equal to w.

For valid numbers, prints zeros after the sign and the base indication and before the digits such that at least w characters are printed ( not counting the fill characters caused by alignment formatting, but still counting the extra fill character caused by fill_sign() ).

p(unsigned precision)

Sets the precision. Effect varies according to the notation ( see below ).

set_float_notation(float_notation)

Sets the float notation ( see below ).

hex()

Equivalent to set_float_notation(float_notation::hex).

fixed()

Equivalent to set_float_notation(float_notation::fixed).

sci()

Equivalent to set_float_notation(float_notation::scientific).

gen()

Equivalent to set_float_notation(float_notation::general).

set_float_format(float_format)

Set all floating-point formatting options simultaneously.

set_float_format(default_float_format)

Reset all floating-point formatting options to default.

And the following observers:

Observer Return type

get_float_format()

float_format, {default_float_format} or an implementation-defined type that sastisfies FloatFormat requirements.

Enumeration float_notation

namespace strf {
enum class float_notation {fixed, scientific, general, hex};
};
float_notation::hex

Hexadecimal

float_notation::fixed

If precision is not set, prints the smallest number of digits such that the floating-point value can be exactly recovered. If precision is set, it is the number of fractional digits.

float_notation::scientific

If precision is not set, prints the smallest number of digits such that the floating-point value can be exactly recovered. If precision is set, it is the number of fractional digits.

float_notation::general

If precision is not set, chooses the notation ( scientific or fixed ) that leads to the smallest number or characters such that the floating-point value can be exactly recovered.
If precision is set, same effect as the 'g' format flags in printf ( except that the lettercase is specified by the lettercase facet ):

  • The precision is the number of significant digts

  • If precision is 0, it is treated as 1

  • Trailing fractional zeros are removed unless operator* is used.

  • Selects the scientific notation iff the resulting exponent is less than -4 or greater than or equal to the precision

Type requirements FloatFormat

Given:

  • F, a FloatFormat type

  • f, a value of type F

The following must hold:

  • F is copy-constructible

  • F is convertible to float_format

  • F has public member variables below:

Member Type Semantics / effect

f.precision

unsigned

Floating-point precision. When it is equal to (unsigned)-1, then precision is considered as not specified, which means that the number or significant digits is such that the value can be fully recovered by a parser. Otherwise, the effect depends on notation.

f.pad0wdith

unsigned

Same as of format function pad0

f.notation

float_notation

See enumeration float_notation

f.sign

showsign

See enumeration showsign

f.showpoint

bool

Equivalent to the '#' format flag in printf

f.punctuate

bool

Activates numeric punctuation.

Struct template float_format

namespace strf {

enum class float_notation {fixed, scientific, general, hex};

struct float_format
{
    unsigned precision = (unsigned)-1;
    unsigned pad0width = 0;
    float_notation notation = float_notation::general
    showsign sign = showsign::negative_only;
    bool showpoint = false;
    bool showpos = false;
};

} // namespace strf

Struct template default_float_format

namespace strf {

struct default_float_format
{
    constexpr static unsigned precision = (unsigned)-1;
    constexpr static unsigned pad0width = 0;
    constexpr static float_notation notation = float_notation::general;
    constexpr static showsign sign = showsign::negative_only;
    constexpr static bool showpoint = false;
    constexpr static bool punctuate = false;

    constexpr operator float_format () const noexcept;
};
} // namespace strf

3.9. Formatter quantity_formatter

The quantity_formatter Formatter defines the following format functions:

Member function Effect

multi(std::size_t count)

Causes the content to be printed count consecutives times

And the following observer:

Observer Return type

count()

std::size_t

4. List of printable types

4.1. Strings

Types

const CharT*, std::string_view<CharT, Traits> and std::basic_string<CharT, Traits, Alloc> :: where: ::

  • CharT is the character type. If it is not the same as the output character type, then it is necessary to use the conv or sani format function.

  • Traits can be any type that satisfies CharTraits

  • Alloc can be any type that satisfies Allocator

Overridable

No

Format functions

( in addition to alignment functions )

p(width_t limit)

Does not print the whole string if its width is greater than limit, but the greatest possible amount of its leading Unicode code points such that the width is not greater than limit.

template <typename Charset> sanitize_from_charset(Charset cs)

Convert the input string from cs to the output charset. If the charsets are the same then sanitizes the input string.

sanitize_charset()

Translates input string from the charset associated to CharT to the output charset. If these charsets are the same then sanitizes the input string.

template <typename Charset> convert_from_charset(Charset cs)

Convert the input string from cs to the output charset, if these charsets are not the same. Otherwise, copies input string as it is.

convert_charset()

Translates input string from the charset associated to CharT to the output charset, if these charsets are not the same. Otherwise, copies the input string as it is.

template <typename Charset> sani(Charset cs)

Equivanlent to sanitize_charset(cs)

template <typename Charset> conv(Charset cs)

Equivanlent to convert_charset(cs)

sani()

Equivalent to sanitize_charset()

conv()

Equivalent to convert_charset()

Example
auto str = strf::to_string(strf::center(u" Hello! ", 16, '*').conv());
assert(str == "**** Hello! ****");

4.2. Single characters

Type

The same as the output character type or char32_t. In the later case, the UTF-32 character is encoded to the destination charset.

Overridable

No

Formatters
Influential facet categories

4.3. bool

Type

bool

Overridable

Yes, override_tag is bool.

Formatters
Influential facet categories

4.4. const void*

Types

const void*

Overridable

Yes, override_tag is const void*

Formatters
Influential facet categories

4.5. Integers

Types

short, int, long int, long long int, unsigned short, unsigned int, unsigned long int and unsigned long long int

Overridable

Yes, override_tag is the same as the input type ( short, int, long int, long long int, unsigned short, unsigned int, unsigned long int or unsigned long long int )

Formatters
Influential facet categories

4.6. Floating Points

Types

float, double

Overridable

Yes, override_tag is the same as the input type ( float or double )

Formatters
Influential facet categories

4.7. Ranges

Without formatting

namespace strf {

template <typename Range>
/*...*/ range(const Range& r);

template <typename T, std::size_t N>
/*...*/ range(T (&array)[N]);

template <typename Iterator>
/*...*/ range(const Iterator& begin, const Iterator& end);

// With operation

template <typename Range, typename UnaryOperation>
/*...*/ range(const Range& r, UnaryOperation unary_op);

template <typename T, std::size_t N, typename UnaryOperation>
/*...*/ range(T (&array)[N], UnaryOperation unary_op);

template <typename Iterator, typename UnaryOperation>
/*...*/ range( const Iterator& begin
             , const Iterator& end
             , UnaryOperation unary_op );

// With separator:

template <typename Range, typename CharT>
/*...*/ separated_range(const Range& r, const CharT* separator);

template <typename T, std::size_t N, typename CharT>
/*...*/ separated_range(T (&array)[N], const CharT* separator);

template <typename Iterator, typename CharT>
/*...*/ separated_range( const Iterator& begin
                       , const Iterator& end
                       , const CharT* separator );

// With separator and operation

template <typename Range, typename CharT, typename UnaryOperation>
/*...*/ separated_range( const Range& r
                       , const CharT* separator
                       , UnaryOperation unary_op );

template <typename T, std::size_t N, typename CharT, typename UnaryOperation>
/*...*/ separated_range( T (&array)[N]
                       , const CharT* separator
                       , UnaryOperation unary_op );

template <typename Iterator, typename CharT, typename UnaryOperation>
/*...*/ separated_range( const Iterator& begin
                       , const Iterator& end
                       , const CharT* separator
                       , UnaryOperation unary_op );
} // namespace strf
Examples
int arr[3] = { 11, 22, 33 };

auto str = strf::to_string(strf::range(arr));
assert(str == "112233");

str = strf::to_string(strf::separated_range(arr, ", "));
assert(str == "11, 22, 33");

auto op = [](auto x){ return strf::join('(', +strf::fmt(x * 10), ')'); };

str = strf::to_string(strf::separated_range(arr, ", ", op));
assert(str == "(+110), (+220), (+330)");

With formatting

namespace strf {

template <typename Range>
/*...*/ fmt_range(const Range& r);

template <typename T, std::size_t N>
/*...*/ fmt_range(T (&array)[N], const Range& r);

template <typename Iterator>
/*...*/ fmt_range(const Iterator& begin, const Iterator& end);

// With separator

template <typename Range, typename CharT>
/*...*/ fmt_separated_range(const Range& r, const CharT* separator);

template <typename T, std::size_t N, typename CharT>
/*...*/ fmt_separated_range(T (&array)[N], const CharT* separator);

template <typename Iterator, typename CharT>
/*...*/ fmt_separated_range( const Iterator& begin
                           , const Iterator& end
                           , const CharT* separator );
} // namespace strf

Any format function applicable to the element type of the range can also be applied to the expression strf::fmt_range(/*...*/) or strf::fmt_separated_range(/*...*/). This way the format functions is applied to all elements:

Example 1
std::vector<int> vec = { 11, 22, 33 };
auto str1 = strf::to_string("[", +strf::fmt_separated_range(vec, " ;") > 4, "]");
assert(str1 == "[ +11 ; +22 ; +33]");
Example 2
std::vector<int> vec = { 11, 22, 33 };
auto str2 = strf::to_string
    ( "["
    , *strf::fmt_separated_range(vec, " / ").fill('.').hex() > 6,
    " ]");

assert(str2 == "[..0xfa / ..0xfb / ..0xfc]");

4.8. Joins

Without alignment

namespace strf {

template <typename ... Args>
/*...*/ join(const Args& ... args);

}

With alignment

You can apply the alignment format functions one the return type of join(args...)

auto str = strf::to_string
    ("---", strf::join("abc", "def", 123) > 15, "---");

assert(str == "---      abcdef123---");

The functions below provide an alternartive syntax to create aligned join. Their return type has the operator()(const Args& ... args) member function that receives the elements of the join.

namespace strf {

enum class text_alignment {left, right, center};

/* ... */ join_align( std::int16_t width
                    , text_alignment align
                    , char32_t fillchar = U' ' );
/* ... */ join_center(int width, char32_t fillchar = U' ');
/* ... */ join_left(int width, char32_t fillchar = U' ');
/* ... */ join_right(int width, char32_t fillchar = U' ');
}
Example
auto str = strf::to_string
    ("---", strf::join_right(15) ("abc", "def", 123), "---");
assert(str == "---      abcdef123---");

str = strf::to_string
    ("---", strf::join_center(15) ("abc", "def", 123), "---");
assert(str == "---   abcdef123   ---");

str = strf::to_string
    ( "---"
    , strf::join_left(15, U'.') ("abc", strf::right("def", 5), 123)
    , "---" );
assert(str == "---abc  def123....---");

4.9. Facets

It is possible to override facets to only a subset of the input arguments.

namespace strf {

template < typename FPack >
class inner_pack
{
public:
    template <typename... Args>
    /*...*/  operator()(const Args&... args) const;
    //...
};

template <typename ... Facets>
inner_pack</*...*/> with(const Facets&... facets);
Example 1
auto str = strf::to_string.with(strf::numpunct<10>(1))
    ( !strf::dec(10000)
    , "  "
    , !strf::hex(0x10000)
    , strf::with( strf::numpunct<10>(3)
                , strf::numpunct<16>(4).thousands_sep('\'') )
        ( "  { "
        , !strf::dec(10000)
        , "  "
        , !strf::hex(0x10000)
        , " }" ) );

assert(str == "1,0,0,0,0  10000  { 10,000  1'0000 }");
Example 2
auto fp = strf::pack
    ( strf::numpunct<10>(3)
    , strf::numpunct<16>(4).thousands_sep('\'') );

auto str = strf::to_string.with(strf::numpunct<10>(1))
    ( !strf::dec(10000)
    , "  "
    , !strf::hex(0x10000)
    , strf::with(fp)
        ( "  { "
        , !strf::dec(10000)
        , "  "
        , !strf::hex(0x10000)
        , strf::with
            (strf::numpunct<10>(2).thousands_sep('.'))
            ("  { ", !strf::dec(10000), " }")
        , " }" ) );

assert(str == "1,0,0,0,0  10000  { 10,000  1'0000  { 1.00.00 } }");

5. Destinations

The destination_no_reserve, destination_reserve_calc and destination_with_given_size class templates provide the basic usage syntax of the library:

syntax
  • no_reserve() always returns a destination_no_reserve object

  • reserve_calc() always returns a destination_reserve_calc object.

  • reserve(size) always returns a destination_with_given_size object.

  • The destination is an expression whose type is an instance of one those three class templates.

5.1. Destination makers

namespace strf {

/* see below */ to(char8_t*  dest,  char8_t*  end);
/* see below */ to(char*     dest,  char*     end);
/* see below */ to(char16_t* dest,  char16_t* end);
/* see below */ to(char32_t* dest,  char32_t* end);
/* see below */ to(wchar_t*  dest,  wchar_t*  end);

} // namespace strf
Return type

destination_no_reserve<OBC>, where OBC is an implementation-defined type that satifies OutbuffCreator.

Return value

A destination object whose internal OutbuffCreator object obc is such that obc.create() returns a basic_cstr_writer<CharT> object initialized with dest and dest_end, where, CharT is std::remove_reference_t<decltype(*dest)>.

namespace strf {

/* see below */ to(char8_t*  dest, std::size_t count);
/* see below */ to(char*     dest, std::size_t count);
/* see below */ to(char16_t* dest, std::size_t count);
/* see below */ to(char32_t* dest, std::size_t count);
/* see below */ to(wchar_t*  dest, std::size_t count);

} // namespace strf
Return type and value

Same as of to(dest, dest + count);

namespace strf {

template<std::size_t N> /* see below */ to(char8_t  (&dest)[N]);
template<std::size_t N> /* see below */ to(char     (&dest)[N]);
template<std::size_t N> /* see below */ to(char16_t (&dest)[N]);
template<std::size_t N> /* see below */ to(char32_t (&dest)[N]);
template<std::size_t N> /* see below */ to(wchar_t  (&dest)[N]);

} // namespace strf
Return type and value

Same as of to(dest, dest + N);

namespace strf {
template <typename CharT>
/* see below */ to_range(CharT* dest, CharT* dest_end);

} // namespace strf
Return type

destination_no_reserve<OBC>, where OBC is an implementation-defined type that satifies OutbuffCreator.

Return value

A destination object whose internal OutbuffCreator object obc is such that obc.create() returns a basic_char_array_writer<CharT> object initialized with dest and dest_end.

namespace strf {
template <typename CharT, std::size_t N>
/* see below */ to_range(CharT (&dest)[N]);

} // namespace strf
Return type and value

Same as of to_range(dest, dest + N);

namespace strf {
template <typename CharT>
/* see below */ to_range(CharT* dest, std::size_t count);

} // namespace strf
Return type and value

Same as of to_range(dest, dest + count);

5.2. Class template destination_no_reserve

template <typename OutbuffCreator, typename FPack = facets_pack<>>
class destination_no_reserve
Compile-time requirements

Synopsis

namespace strf {

template <typename OutbuffCreator, typename FPack>
class destination_no_reserve
{
public:
    using char_type = typename OutbuffCreator::char_type;

    // constructors
    template <typename... Args>
    constexpr destination_no_reserve(Args&&...);
    constexpr destination_no_reserve(const destination_no_reserve&);
    constexpr destination_no_reserve(destination_no_reserve&&);

    // facets
    template <typename... FPE>
    destination_no_reserve<OutbuffCreator, /*...*/> with(FPE&&...) const &;

    template <typename... FPE>
    destination_no_reserve<OutbuffCreator, /*...*/> with(FPE&&...) &&;

    // size reserve
    constexpr destination_calc_size<OutbuffCreator, FPack>
    reserve_calc() const &;

    constexpr destination_calc_size<OutbuffCreator, FPack>
    reserve_calc() &&;

    constexpr destination_with_given_size<OutbuffCreator, FPack>
    reserve(std::size_t) const &;

    constexpr destination_with_given_size<OutbuffCreator, FPack>
    reserve(std::size_t) &&;

    constexpr destination_no_reserve&  no_reserve() &;
    constexpr destination_no_reserve&& no_reserve() &&;
    constexpr const destination_no_reserve&  no_reserve() const &;
    constexpr const destination_no_reserve&& no_reserve() const &&;

    // printing
    template <typename... Args>
    /*...*/ operator()(const Args&...) const;

    template <typename... Args>
    /*...*/ tr(const char_type*, const Args&...) const;

    template <typename... Args>
    /*...*/ tr( const std::basic_string_view<char_type>&
              , const Args&...) const;

    template <typename... Args>
    /*...*/ tr( std::basic_string_view<char_type>
              , const Args&...) const;

private:
    OutbuffCreator _outbuff_creator; // exposition only
    FPack _fpack;                    // exposition only
};

} // namespace strf

Public member functions

Constructors
template <typename... Args>
constexpr destination_no_reserve(Args&&... args);
Compile-time requirements
  • FPack is DefaultConstructible

  • std::is_constructible<OutbuffCreator, Args...> is true, otherwise this constructor does not participate on overload resolution.

Effect
  • Initializes _outbuff_creator with std::forward<Args>(args)....

constexpr destination_no_reserve(const destination_no_reserve&) = default;

Copy constructor.

Compile-time requirements
constexpr destination_no_reserve(destination_no_reserve&&) = default;

Move constructor.

Facets
template <typename... FPE>
/* see below */ with(FPE&&...) const &;
Compile-time requirements
Return Type
destination_no_reserve< OutbuffCreator
                      , decltype(pack( std::declval<const FPack&>()
                                     , std::forward<FPE>(fpe)...) ) >
Effect

Creates a destination_no_reserve object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with pack(this->_fpack, std::forward<FPE>(fpe)...)

template <typename... FPE>
/* see below */ with(FPE&&...) &&;
Compile-time requirements
Return Type
destination_no_reserve< OutbuffCreator
                      , decltype(pack( std::declval<const FPack&>()
                                     , std::forward<FPE>(fpe)...) ) >
Effect

Creates an destination_no_reserve object whose _outbuff_creator is initialized with std::move(_outbuff_creator), and whose _fpack is initialized with pack(std::move(this->_fpack), std::forward<FPE>(fpe)...)

Size reserve
constexpr destination_calc_size<OutbuffCreator, FPack> reserve_calc() const &;
Compile-time requirements
Effect

Creates an destination_calc_size object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_calc_size<OutbuffCreator, FPack> reserve_calc() &&;
Compile-time requirements
Effect

Creates an destination_calc_size object whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose _fpack object is initialized with std::move(_fpack) from this object.

constexpr destination_with_given_size<OutbuffCreator, FPack>
reserve(std::size_t size) const &;
Compile-time requirements
Effect

Creates an destination_with_given_size whose _size is initialized with size, whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_with_given_size<OutbuffCreator, FPack>
reserve(std::size_t size) &&;
Compile-time requirements

OutbuffCreator is MoveConstructible and SizedOutbuffCreator.

Effect

Creates an destination_with_given_size object whose _size is initialized with size, whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose `_fpack is initialized with std::move(_fpack) from this object.

constexpr destination_no_reserve&  no_reserve() &;
constexpr destination_no_reserve&& no_reserve() &&;
constexpr const destination_no_reserve&  no_reserve() const &;
constexpr const destination_no_reserve&& no_reserve() const &&;
Effect

None.

Return

This object.

Printing
template <typename... Args>
/*...*/ operator()(const Args&... args) const;
Compile-time requirements
Effect
  1. Creates the outbuff object doing

    typename OutbuffCreator::outbuff_type ob{_outbuff_creator.create()};
  2. For each arg in args..., does

    using preview_type = print_preview<preview_size::no, preview_width::no>;
    preview_type preview;
    using printer_type = printer_type<char_type, preview_type, FPack, Arg>;
    printer_type p{ make_printer_input<char_type>(preview, _fpack, arg) };
    static_cast<const printer<char_type>&>(p).print_to(ob);

    where Arg is the type in Args... corresponding to arg

  3. Returns ob.finish() if such expression is valid, which is optional. Otherwise the return type is void.

template <typename …​ Args>
/*...*/ tr( const char_type* tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( const std::basic_string_view<char_type>& tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( std::basic_string_view<char_type> tr_string
          , const Args&... args) const;
Compile-time requirements
Effect

to-do

5.3. Class template destination_calc_size

template <typename SizedOutbuffCreator, typename FPack = facets_pack<>>
class destination_calc_size;
Compile-time requirements

Synopsis

namespace strf {

template <typename SizedOutbuffCreator, typename FPack>
class destination_reserve_calc
{
public:
    using char_type = typename SizedOutbuffCreator::char_type;

    // constructors
    template <typename... Args>
    constexpr destination_reserve_calc(Args&&...);

    constexpr destination_reserve_calc(const destination_reserve_calc&) = default;
    constexpr destination_reserve_calc(destination_reserve_calc&&) = default;

    // facets
    template <typename... FPE>
    destination_reserve_calc<SizedOutbuffCreator, /*...*/> with(FPE&&...) const &;

    template <typename... FPE>
    destination_reserve_calc<SizedOutbuffCreator, /*...*/> with(FPE&&...) &&;

    // size reserve
    constexpr destination_no_reserve<SizedOutbuffCreator, FPack>
    no_reserve() const &;

    constexpr destination_no_reserve<SizedOutbuffCreator, FPack>
    no_reserve() &&;

    constexpr destination_with_given_size<SizedOutbuffCreator, FPack>
    reserve(std::size_t) const &;

    constexpr destination_with_given_size<SizedOutbuffCreator, FPack>
    reserve(std::size_t) &&;

    constexpr destination_reserve_calc&  reserve_calc() &;
    constexpr destination_reserve_calc&& reserve_calc() &&;
    constexpr const destination_reserve_calc&  reserve_calc() const &;
    constexpr const destination_reserve_calc&& reserve_calc() const &&;

    // printing
    template <typename... Args>
    /*...*/ operator()(const Args&...) const;

    template <typename... Args>
    /*...*/ tr(const char_type*, const Args&...) const;

    template <typename... Args>
    /*...*/ tr(const std::basic_string<char_type>&, const Args&...) const;

    template <typename... Args>
    /*...*/ tr(std::basic_string_view<char_type>, const Args&...) const;

private:
    OutbuffCreator _outbuff_creator; // exposition only
    FPack _fpack;                    // exposition only
};

} // namespace strf
Constructors
template <typename... Args>
constexpr destination_reserve_calc(Args&&... args);
Compile-time requirements
  • FPack is DefaultConstructible

  • std::is_constructible<OutbuffCreator, Args...>::value is true, otherwise this constructor does not participate on overload resolution.

Effect
  • Initializes _outbuff_creator with std::forward<Args>(args)....

constexpr destination_reserve_calc(const destination_reserve_calc&) = default;

Copy constructor.

Compile-time requirements
constexpr destination_reserve_calc(destination_reserve_calc&&) = default;

Move constructor.

Facets
template <typename... FPE>
/* see below */ with(FPE&&...) const &;
Compile-time requirements
Return Type
destination_reserve_calc< OutbuffCreator
                        , decltype(pack( std::declval<const FPack&>()
                                       , std::forward<FPE>(fpe)...) ) >
Effect

Creates an destination_reserve_calc object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with pack(this->_fpack, std::forward<FPE>(fpe)...)

template <typename... FPE>
/* see below */ with(FPE&&...) &&;
Compile-time requirements
Return Type
destination_reserve_calc< OutbuffCreator
                        , decltype(pack( std::declval<const FPack&>()
                                       , std::forward<FPE>(fpe)...) ) >
Effect

Creates an destination_reserve_calc object whose _outbuff_creator is initialized with std::move(this->_outbuff_creator), and whose _fpack is initialized with pack(std::move(this->_fpack), std::forward<FPE>(fpe)...)

Size reserve
constexpr destination_no_reserve<OutbuffCreator, FPack> no_reserve() const &;
Compile-time requirements
Effect

Creates an destination_no_reserve object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_calc_size<OutbuffCreator, FPack> reserve_calc() &&;
Compile-time requirements
Effect

Creates an destination_no_reserve object whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose _fpack object is initialized with std::move(_fpack) from this object.

constexpr destination_with_given_size<OutbuffCreator, FPack>
reserve(std::size_t size) const &;
Compile-time requirements
Effect

Creates an destination_with_given_size whose _size is initialized with size, whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_with_given_size<OutbuffCreator, FPack>
reserve(std::size_t) &&;
Compile-time requirements

OutbuffCreator is MoveConstructible and SizedOutbuffCreator.

Effect

Creates an destination_with_given_size object whose _size is initialized with size, whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose `_fpack is initialized with std::move(_fpack) from this object.

constexpr destination_reserve_calc&  reserve_calc() &;
constexpr destination_reserve_calc&& reserve_calc() &&;
constexpr const destination_reserve_calc&  reserve_calc() const &;
constexpr const destination_reserve_calc&& reserve_calc() const &&;
Effect

None.

Return

This object.

Printing
template <typename... Args>
/*...*/ operator()(const Args&... args) const;
Compile-time requirements
Effect
  1. Creates an object preview of type print_preview<preview_size::yes, preview_width::no>.

    using preview_type = print_preview<preview_size::yes, preview_width::no>;
    preview_type preview;
  2. For each arg in args..., creates a printer object by doing:

    using printer_type = printer_type<char_type, preview_type, FPack, Arg>;
    printer_type p{ make_printer_input<char_type>(preview, _fpack, arg) };
  3. Creates/get the outbuff object doing

    using ob_type = typename OutbuffCreator::size_outbuf_type;
    ob_type ob{_outbuff_creator.create(preview.accumulated_size())};
  4. For each p object does:

    static_cast<const printer<char_type>&>(p).print_to(ob);
  5. Returns ob.finish() if such expression is valid, which is optional. Otherwise the return type is void.

template <typename …​ Args>
/*...*/ tr( const char_type* tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( const std::basic_string_view<char_type>& tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( std::basic_string_view<char_type> tr_string
          , const Args&... args) const;
Compile-time requirements
Effect

to-do

5.4. Class template destination_with_given_size

template <typename SizedOutbuffCreator, typename FPack = facets_pack<>>
class destination_with_given_size
Compile-time requirements

Synopsis

namespace strf {

template <typename SizedOutbuffCreator, typename FPack>
class destination_with_given_size
{
public:
    using char_type = typename SizedOutbuffCreator::char_type;

    // constructors
    template <typename... Args>
    constexpr destination_with_given_size(std::size_t, Args&&...);
    constexpr destination_with_given_size(const destination_with_given_size&) = default;
    constexpr destination_with_given_size(destination_with_given_size&&) = default;

    // facets
    template <typename... FPE>
    destination_with_given_size<SizedOutbuffCreator, /*...*/> with(FPE&&...) const &;

    template <typename... FPE>
    destination_with_given_size<SizedOutbuffCreator, /*...*/> with(FPE&&...) &&;

    // size reserve
    constexpr destination_calc_size<SizedOutbuffCreator, FPack>
    reserve_calc() const &;

    constexpr destination_calc_size<SizedOutbuffCreator, FPack>
    reserve_calc() &&;

    constexpr destination_no_reserve<SizedOutbuffCreator, FPack>
    no_reserve() const &;

    constexpr destination_no_reserve<SizedOutbuffCreator, FPack>
    no_reserve() &&;

    constexpr destination_with_given_size&  reserve(std::size_t) &;
    constexpr destination_with_given_size&& reserve(std::size_t) &&;
    constexpr destination_with_given_size   reserve(std::size_t) const &;
    constexpr destination_with_given_size   reserve(std::size_t) const &&;

    // printing
    template <typename... Args>
    /*...*/ operator()(const Args&...) const;

    template <typename... Args>
    /*...*/ tr(const char_type*, const Args&...) const;

    template <typename... Args>
    /*...*/ tr(const std::basic_string<char_type>&, const Args&...) const;

    template <typename... Args>
    /*...*/ tr(std::basic_string_view<char_type>, const Args&...) const;

private:
    std::size_t _size              // exposition only
    OutbuffCreator _outbuff_creator; // exposition only
    FPack _fpack;                  // exposition only
};

} // namespace strf
Constructors
template <typename... Args>
constexpr destination_with_given_size(std::size_t size, Args&&... args);
Compile-time requirements
  • FPack is DefaultConstructible

  • std::is_constructible<OutbuffCreator, Args...>, otherwise this constructor does not participate on overload resolution.

Effect
  • Initializes _outbuff_creator with std::forward<Args>(args)....

  • Initializes _size with size

constexpr destination_with_given_size(const destination_with_given_size&) = default;

Copy constructor.

Compile-time requirements
constexpr destination_with_given_size(destination_with_given_size&&) = default;

Move constructor.

Facets
template <typename... FPE>
/* see below */ with(FPE&&...) const &;
Compile-time requirements
Return Type
destination_with_given_size< OutbuffCreator
                           , decltype(pack( std::declval<const FPack&>()
                                          , std::forward<FPE>(fpe)...) ) >
Effect

Creates an destination_with_given_size object whose _size is is initialized with this _size , whose _outbuff_creator is initialized with this _outbuff_creator , and whose _fpack is initialized with pack(this->_fpack, std::forward<FPE>(fpe)...)

template <typename... FPE>
/* see below */ with(FPE&&...) &&;
Compile-time requirements
Return Type
destination_with_given_size< OutbuffCreator
                           , decltype(pack( std::declval<const FPack&>()
                                          , std::forward<FPE>(fpe)...) ) >
Effect

Creates an destination_with_given_size object whose _size is is initialized with this _size , whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object , and whose _fpack is initialized with pack(std::move(this->_fpack), std::forward<FPE>(fpe)...)

Size reserve
constexpr destination_no_reserve<OutbuffCreator, FPack> no_reserve() const &;
Compile-time requirements
Effect

Creates an destination_no_reserve object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_calc_size<OutbuffCreator, FPack> no_reserve() &&;
Compile-time requirements
Effect

Creates an destination_no_reserve object whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose _fpack object is initialized with std::move(_fpack) from this object.

constexpr destination_calc_size<OutbuffCreator, FPack> reserve_calc() const &;
Compile-time requirements
Effect

Creates an destination_calc_size object whose _outbuff_creator is initialized with this _outbuff_creator, and whose _fpack is initialized with this _fpack.

constexpr destination_calc_size<OutbuffCreator, FPack> reserve_calc() &&;
Compile-time requirements
Effect

Creates an destination_calc_size object whose _outbuff_creator is initialized with std::move(_outbuff_creator) from this object, and whose _fpack object is initialized with std::move(_fpack) from this object.

constexpr destination_with_given_size&  reserve(std::size_t size) &;
constexpr destination_with_given_size&& reserve(std::size_t size) &&;
Effect

assign size to _size.

Return

This object.

constexpr destination_with_given_size reserve(std::size_t size) const &;
constexpr destination_with_given_size reserve(std::size_t size) const &&;
Effect

Creates an destination_with_give_size object whose _size is initialized with size, whose _outbuff_creator is initialized with this _outbuff_creator, and whose facets_pack object with this _fpack.

Printing
template <typename... Args>
/*...*/ operator()(const Args&... args) const;
Compile-time requirements
Effect
  1. Creates/get the outbuff object doing

    decltype(auto) ob = _outbuff_creator.create(_size)
  2. For each arg in args... does:

    using preview_type = print_preview<preview_size::no, preview_width::no>;
    preview_type preview;
    using printer_type = printer_type<char_type, preview_type, FPack, Arg>;
    printer_type p{ make_printer_input<char_type>(preview, _fpack, arg) };
    static_cast<const printer<char_type>&>(p).print_to(ob);

    , where Arg is the type in Args... corresponding to arg

  3. Returns ob.finish() if such expression is valid, which is optional. Otherwise the return type is void.

template <typename …​ Args>
/*...*/ tr( const char_type* tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( const std::basic_string_view<char_type>& tr_string
          , const Args&... args) const;

template <typename …​ Args>
/*...*/ tr( std::basic_string_view<char_type> tr_string
          , const Args&... args) const;
Compile-time requirements
Effect

to-do

5.5. Type requirement OutbuffCreator

Given

  • char_type, a character type

  • X, an OutbuffCreator type for char_type

  • x, an expression of type X or const X

The following must hold:

  • X is CopyConstructible

  • X has a member type alias X::char_type defined as char_type

  • X has the X::outbuff_type that is a type alias to a concrete type that is derives from basic_outbuff<X::char_type>

And the following expression must be well-formed:

typename X::outbuff_type{x.create()}

5.6. Type requirement SizedOutbuffCreator

Given

  • char_type, a character type

  • size, a value of the std::size_t

  • X, an SizedOutbuffCreator type for char_type

  • x, an expression of type X or const X

The following must hold:

  • X is CopyConstructible

  • X has a member type alias T::char_type defined as char_type

  • X has the X::sized_outbuff_type that is a type alias to a concrete type that derives from basic_outbuff<X::char_type>

And the following expression must be well-formed:

typename X::sized_outbuff_type{x.create(size)}

6. Tr-String

6.1. Syntax

A '{' followed by until means

'-'

the next '}' or end of string

a comment

a digit

the next '}' or end of string

a positional argument reference

another '{'

the second '{'

an escaped '{'

any other character

the next '}' or end of string

a non positional argument reference

Examples:

Comments
auto str = strf::to_string.tr
    ( "You can learn more about python{-the programming language, not the reptile} at {}"
    , "www.python.org" );
assert(str == "You can learn more about python at www.python.org");
Positional arguments
auto str = strf::to_string.tr("{1 a person} likes {0 a food type}.", "sandwich", "Paul");
assert(str == "Paul likes sandwich.");
Non positional arguments
auto str = strf::to_string.tr("{a person} likes {a food type}.", "Paul", "sandwich");
assert(str == "Paul likes sandwich.");
Escapes
auto str = strf::to_string.tr("} {{x} {{{} {{{}}", "aaa", "bbb");
assert(str == "} {x} {aaa {bbb}");

Syntax error handling

When the argument associated with a "{" does not exists, the library does two things:

  • It prints a replacement character "\uFFFD" (�) ( or "?" when the charset can’t represent it ) where the missing argument would be printed.

  • It calls the handle function on the facet object correspoding to the tr_error_notifier_c category.

6.2. Facet category tr_error_notifier_c

For a type to be a facet of the tr_error_notifier_c, it must satisfy the requirements of TrErrorHandling

namespace strf {

struct tr_error_notifier_c {
    static constexpr default_tr_error_notifier get_default() noexcept
    {
        return default_tr_error_notifier{};
    }
};

} // namespace strf

Struct default_tr_error_notifier

default_tr_error_notifier is the default facet of the tr_error_notifier_c category. It’s a dummy error handler.

namespace strf {

struct default_tr_error_notifier {
    using category = tr_error_notifier_c;

    template <typename Charset>
    void handle
        ( const typename Charset::{code_unit}* str
        , std::size_t str_len
        , std::size_t err_pos
        , Charset charset ) noexcept
    {
    }
};

} // namespace strf

Type requirement TrErrorHandling

Given:

  • X, a TrErrorHandling type

  • x, a value of type X

  • CharsetT, a Charset type.

  • charset, a value of type CharsetT

  • str, a value of type const CharsetT::code_unit* pointing to string encoded according to charset

  • str_len, a std::size_t value equal to the length of the string str

  • err_pos, a std::size_t value less than or equal to str_len

The following must host:

  • X is CopyConstructible.

  • X::category is a type alias to tr_error_notifier_c

  • The following expression is supported:

x.handle(str, str_len, err_pos, charset)
Semantics

str is a tr-string that contains an error. err_pos is the position of the '{' character in str that starts the invalid argument reference.

7. Numeric punctuation

7.1. Facet category template numpunct_c

namespace strf {
template <int Base> struct numpunct_c {
    constexpr static bool constrainable = true;
    static constexpr default_numpunct<Base> get_default() noexcept;
};
} // namespace strf

For a type to be a facet of the numpunct_c<Base>, it must satisfy NumericPuntuation type requirements

7.2. Type requirement NumericPunctuation

Given

  • Base, an integer constexpr equal to 2, 8, 10 or 16

  • X, a NumericPunctuation type for Base

  • x, a const value of type X

The following must hold:

And following expressions are well-formed and satisfy the following corresponding conditions:

static_cast<numpunct<Base>>(x)

( X is explicitly convertible to numpunct<Base> )

x.grouping()
Return type

digits_grouping

x.distribute(digcount)
Return type

digits_distribution

Return value

x.grouping().distribute(digcount)

x.any_group_separation(digcount)
Return type

bool

Return value

x.grouping().any_separator(digcount)

x.thousands_sep_count(digcount)
Return type

unsigned

Return value

x.grouping().separators_count(digcount)

x.thousands_sep()
Return type

char32_t

x.decimal_point()
Return type

char32_t

7.3. Class template numpunct

numpunct<Base> is a facet of the numpunct_c<_Base_> category,
and it satisfies the requirements of NumericPunctuation.

template <int Base>
class numpunct {
public:
    using category = numpunct_c<Base>;

    // constructors
    constexpr numpunct() noexcept;
    constexpr numpunct(const numpunct& ) noexcept;

    constexpr explicit numpunct(digits_grouping) noexcept;

    template <typename... IntArgs>
    constexpr explicit numpunct(int grp0, IntArgs... grps) noexcept;

    // assignment
    constexpr numpunct& operator=(const numpunct&) noexcept;

    // comparison
    constexpr bool operator==(const numpunct& other) const noexcept;
    constexpr bool operator!=(const numpunct& other) const noexcept;

    // observers
    constexpr char32_t   decimal_point() const noexcept;
    constexpr char32_t   thousands_sep() const noexcept;
    constexpr digits_grouping grouping() const noexcept;

    // modifiers
    constexpr numpunct&  decimal_point(char32_t ch) & noexcept;
    constexpr numpunct&& decimal_point(char32_t ch) && noexcept;

    constexpr numpunct&  thousands_sep(char32_t ch) & noexcept;
    constexpr numpunct&& thousands_sep(char32_t ch) && noexcept;

    // utilities
    constexpr digits_distribution distribute(unsiged digcount) const noexcept;
    constexpr bool any_group_separation(unsigned digcount) const noexcept;
    constexpr STRF_HD unsigned thousands_sep_count(unsigned digcount) const noexcept;

private:
    char32_t decimal_point_ = U'.';  // exposition only
    char32_t thousands_sep_ = U',';  // exposition only
    digits_grouping grouping_;     // exposition only
};

Public members

constexpr numpunct() noexcept;
Postconditions
  • decimal_point() == U'.'

  • thousands_separator() == U','

  • grouping().empty()

constexpr numpunct(digits_grouping grpng) noexcept;
Postconditions
  • decimal_point() == U'.'

  • thousands_separator() == U','

  • grouping() == grpng

template <typename... IntArgs>
constexpr numpunct(int grp0, IntArgs... grps) noexcept;
Preconditions

Same as of the constructor of digits_grouping ( see here ).

Postconditions
  • decimal_point() == U'.'

  • thousands_sep() == U','

  • grouping() == digits_grouping{grp0, grps...};

unsigned thousands_sep_count(unsigned digcount) const;
Return value

grouping().separators_count(digcount))

constexpr digits_distribution distribute(unsiged digcount) const noexcept;
Return value

grouping().distribute(digcount))

bool any_group_separation(unsigned digcount) const;
Return value

grouping().any_separator(digcount)

char32_t decimal_point() const noexcept;

Returns the decimal point.

char32_t thousands_sep() const noexcept;

Returns the thousands separator.

numpunct &  decimal_point(char32_t ch) &  noexcept;
numpunct && decimal_point(char32_t ch) && noexcept;
Effect

Changes the decimal point to ch.

Postcondition

decimal_point() == ch

Return value

*this or std::move(*this)

numpunct &  thousands_sep(char32_t ch) &  noexcept;
numpunct && thousands_sep(char32_t ch) && noexcept;
Effect

Changes the thousands separtor to ch.

Postcondition

thousands_sep() == ch

Return value

*this or std::move(*this)

7.4. Class template default_numpunct

default_numpunct<Base> is the default facet of the numpunct_c<Base> category. It is an empty class, optimized to represent the default state of numpunct<Base>

namespace strf {
template <int Base>
class default_numpunct: {
public:
    using category = numpunct_c<Base>;

    constexpr default_numpunct() noexcept= default; // no-op
    constexpr default_numpunct(const default_numpunct& ) noexcept = default; // no-op
    constexpr default_numpunct& operator=(const default_numpunct&) noexcept; // no-op
    constexpr bool operator==(const default_numpunct& other) const noexcept;
    constexpr bool operator!=(const default_numpunct& other) const noexcept;

    constexpr digits_grouping grouping() const
    constexpr digits_distribution distribute(unsiged digcount) const

    constexpr bool any_group_separation(unsigned digcount) const noexcept;
    constexpr STRF_HD unsigned thousands_sep_count(unsigned digcount) const noexcept;

    constexpr char32_t decimal_point() const noexcept;
    constexpr char32_t thousands_sep() const noexcept;
};
} // namespace strf

Public members

constexpr bool operator==(const default_numpunct& other) const noexcept;
Return value

true

constexpr bool operator!=(const default_numpunct& other) const noexcept;
Return value

false

constexpr digits_grouping grouping() const
Return value

digits_grouping{}

constexpr digits_distribution distribute(unsiged digcount) const
Return value

digits_distribution{{}, 0, digcount}

constexpr bool any_group_separation(unsigned digcount) const noexcept;
Return value

false

unsigned thousands_sep_count(unsigned digcount) const override;
Return value

0

char32_t thousands_sep() const noexcept;
Return value

U','

char32_t decimal_point() const noexcept;
Return value

U'.'

7.5. Class template no_grouping

no_grouping<_Base_> is a facet of the numpunct_c<_Base_ category. The only reason for one to use no_grouping rather than numpunct is optimization. It is not possible to change the thousaunds separator nor the grouping in a no_grouping<_Base_> object. It is only possible to change its decimal point.

namespace strf {
template <int Base>
class no_grouping {
public:
    using category = numpunct_c<Base>;

    constexpr no_grouping() = default;
    constexpr no_grouping(const no_grouping& ) = default;
    constexpr no_grouping& operator=(const no_grouping&) noexcept;
    constexpr bool operator==(const no_grouping& other) const noexcept;
    constexpr bool operator!=(const no_grouping& other) const noexcept;

    constexpr digits_grouping grouping() const
    constexpr digits_distribution distribute(unsiged digcount) const

    constexpr bool any_group_separation(unsigned digcount) const noexcept;
    constexpr STRF_HD unsigned thousands_sep_count(unsigned digcount) const noexcept;

    constexpr char32_t   decimal_point() const noexcept;
    constexpr no_grouping&  decimal_point(char32_t ch) & noexcept;
    constexpr no_grouping&& decimal_point(char32_t ch) && noexcept;

    constexpr char32_t   thousands_sep() const noexcept;

private:
    char32_t decimal_point_ = U'.';  // exposition only
};

} // namespace strf

Public members

constexpr bool operator==(const no_grouping& other) const noexcept;
Return value

decimal_point() == other.decimal_point()

constexpr bool operator!=(const no_grouping& other) const noexcept;
Return value

decimal_point() != other.decimal_point()

constexpr digits_grouping grouping() const
Return value

digits_grouping{}

constexpr digits_distribution distribute(unsiged digcount) const
Return value

digits_distribution{{}, 0, digcount}

constexpr bool any_group_separation(unsigned digcount) const noexcept;
Return value

false

unsigned thousands_sep_count(unsigned digcount) const override;
Return value

0

unsigned thousands_sep_count(unsigned digcount) const override;
Return value

0

char32_t thousands_sep() const noexcept;
Return value

U','

char32_t decimal_point() const noexcept;
Return value
no_grouping &  decimal_point(char32_t ch) &  noexcept;
no_grouping && decimal_point(char32_t ch) && noexcept;
Effect

Changes the decimal point to ch.

Postcondition

decimal_point() == ch

Return value

*this or std::move(*this)

7.6. Class digits_grouping

namespace strf {
class digits_grouping {
public:
    constexpr static int grp_max = 31;
    constexpr static unsigned grps_count_max = 6;

    // constructors
    constexpr digits_grouping() noexcept;
    constexpr digits_grouping(const digits_grouping&) noexcept;

    template <typename... IntArgs>
    constexpr explicit digits_grouping(int grp0, IntArgs... grps) noexcept;

    explicit digits_grouping(const char* str) noexcept;

    // assignment
    constexpr digits_grouping& operator=(const digits_grouping&) noexcept;

    // comparison
    constexpr bool operator==(const digits_grouping&) const noexcept;
    constexpr bool operator!=(const digits_grouping&) const noexcept;

    // observers and utilities
    constexpr bool empty() const noexcept;
    constexpr bool any_separator(int digcount) const noexcept;
    constexpr unsigned separators_count(int digcount) const noexcept;
    constexpr digits_grouping_iterator get_iterator() const noexcept;
    constexpr digits_distribution distribute(unsigned digcount) const noexcept;
};
} // namespace strf
constexpr explicit digits_grouping() noexcept;

Equivalent to digits_grouping(-1)

Postcondition

empty() returns true

template <typename... IntArgs>
constexpr explicit digits_grouping(int grp0, IntArgs... grps) noexcept;

Specifies the groups from the least significant ( first argument ) to the most significant. If the last argument is -1, then the last group ( second-to-last argument ) is not to be repeated.

Compile-time requirements
  • All arguments are convertible to int

Preconditions
  • The value g of last argument is such that g == -1 || (0 < g && g <= grp_max) is true.

  • The value g of any argument but the last is such that (0 < g && g <= grp_max) is true.

  • The number of groups ( not counting the last argument if it’s -1 ) is not greater than grps_count_max

dexplicit igits_grouping(const char* str) noexcept;

The characters in str specify the groups, starting from the least significant one. If the last character is '\xFF', then the last group is not repeated. Passing the empty string ("") has the same effect as passing as "\xFF", which has the same effect of the default constructor.

Preconditions
  • str != nullptr

  • str is a null terminated string

  • For each character ch in str that is not the last character, 0 < ch && ch <= grp_max is true

  • If ch is the last character str, then ch == '\xFF' || (0 < ch && ch <= grp_max) is true

  • The number of groups ( not counting the last character if it is '\xFF' ) must not be greater than grps_count_max.

constexpr bool empty() const noexcept;

If empty() return true, then there is no group. This means that the thousands separator is absent regardless of the number of digits.

constexpr bool any_separator(int digcount) const noexcept;
Return value

separators_count(digcount) != 0

constexpr unsigned separators_count(int digcount) const noexcept;
Return value

The quantity of thousands separators that would appear in digcount digits.

constexpr digits_grouping_iterator get_iterator() const noexcept;

Constructs a digits_grouping_iterator from this object. It is supposed to be used when the digits are to be written backwards, i.e. from the the least to the most significant.

constexpr digits_distribution distribute(unsigned digcount) const noexcept;

Constructs a digits_distribution from this object. It is supposed to be used when the digits are to be written forwards, i.e. from the the most to the least significant.

digcount is the quantity of digits.

Precondition

digcount > 0

Postconditions

The return value dist is such that

  • dist.highest_group > 0

  • if dist.middle_groups_count is not 0, then dist.low_groups.empty() is false.

7.7. Class digits_grouping_creator

namespace strf {
class digits_grouping_creator {
public:
    constexpr digits_grouping_creator() noexcept = default;
    constexpr digits_grouping_creator(const digits_grouping_creator&) noexcept = delete;
    constexpr void push_high(int grp) noexcept;
    constexpr bool failed() const noexcept;
    constexpr digits_grouping finish_no_more_sep() noexcept;
    constexpr digits_grouping finish() noexcept;
};
} // namespace strf

Sometimes it is not easy instantiate to digits_grouping through one of its constructors, since it requires you to pass all groups at once. So digits_grouping_creator provides an alternative and iterative way: each groups is passed one-by-one to push_high function, from the least to the most significant. After all groups are passed, finish() or finish_no_more_sep() shall be called to create the resulting digits_grouping object. finish() is used when the last group is supposed to be repeated, while finish_no_more_sep() is for the opposite case. Calling push_high() after that has undefined behaviour.

Example
strf::digits_grouping_creator creator;
creator.push_high(1);
creator.push_high(2);
creator.push_high(3);
assert(creator.finish() == strf::digits_grouping(1, 2, 3));

If something wrong happens ( push_high called more than digits_grouping::grps_count_max, or with an invalid argument ( 0 or greater than digits_grouping::grp_max ) ) , the return value of failed() becames true, and the return value of finish() and finish_no_more_sep() becames digits_grouping{}.

7.8. Class digits_grouping_iterator

This class provides a way to iterate through the groups of a digits_grouping object, from the least to the most significant.

namespace strf {
class digits_grouping_iterator {
public:
    // constructors
    digits_grouping_iterator() = delete;
    constexpr digits_grouping_iterator(const digits_grouping_iterator&) noexcept = default;
    constexpr explicit digits_grouping_iterator(digits_grouping) noexcept;

    // assignment
    constexpr digits_grouping_iterator& operator=(const digits_grouping_iterator&) noexcept;

    // comparison
    constexpr bool operator==(const digits_grouping_iterator&) const noexcept;
    constexpr bool operator!=(const digits_grouping_iterator&) const noexcept;

    // iteration
    constexpr unsigned current() const noexcept;
    constexpr void advance() noexcept;
    constexpr bool is_last() const noexcept;
    constexpr bool shall_repeat_current() const noexcept;
    constexpr bool is_final() const noexcept;
    constexpr bool ended() const noexcept;
};
} // namespace strf
constexpr unsigned current() noexcept;

Returns the current group.

Precondition

ended() returns false.

constexpr void advance() noexcept;
Effect

Moves to the next (more significant) group.

Precondition

ended() returns false.

Postconditions

If the return value of is_last() is true, then it becames false and return value of ended() becames true.

constexpr bool is_last() const noexcept;
Return value

true is this is the last group. It is equall to is_final() || shall_repaete_current().

constexpr bool shall_repated_current() const noexcept;
Return value

true is this is the last group and it shall be repeated. It is equall to (is_last() && ! is_final()).

constexpr bool is_final() const noexcept;
Return value

true is this is the last group and it shall not be repeated. It is equall to (is_last() && ! shall_repeat_current()).

constexpr bool ended() const noexcept;

Returns true when there is no group left.

Example
strf::digits_grouping grouping{1, 2, 3};
strf::digits_grouping_iterator it = grouping.get_iterator();

assert(it.current() == 1 && ! it.is_last());
it.advance();
assert(it.current() == 2 && ! it.is_last());
it.advance();
assert(it.current() == 3 && it.shall_repeat_current());
it.advance();
assert(it.ended());
Example
strf::digits_grouping grouping{1, 2, 3, -1};
strf::digits_grouping_iterator it = grouping.get_iterator();

assert(it.current() == 1 && ! it.is_last());
it.advance();
assert(it.current() == 2 && ! it.is_last());
it.advance();
assert(it.current() == 3 && it.is_final());
it.advance();
assert(it.ended());
Example
strf::digits_grouping grouping{};
strf::digits_grouping_iterator it = grouping.get_iterator();
assert(it.ended());

7.9. Class digits_distribution

This struct is designed to be used in algoritms that print groups of digits separated by the thousands separator from the most to the least significant.

namespace strf {
struct digits_distribution {
    reverse_digits_groups low_groups;
    unsigned middle_groups_count;
    unsigned highest_group;
};
} // namespace strf
  • highest_group is the most significant group.

  • low_groups contains the least signficant groups.

  • middle_groups_count how many groups equal to low_groups.highest_groups() follow the highest group.

Example
strf::numpunct<Base> punct = …​;
strf::digits_distribution dist = punct.distribute(digits_count);
assert(dist.highest_groups != 0);

// step 1
…​ // print the most significant dist.highest_group digits

// step 2 - print middle groups
if (dist.middle_groups_count) {
    auto mg = dist.low_groups.highest_group();
    dist.low_groups.pop_high();
    do {
        …​ // print the separator, then mg digits
    } while (--dist.middle_groups_count);
}

// step 3 - least significant groups
while( ! dist.low_groups.empty()) {
    auto g = dist.low_groups.highest_group();
    dist.low_groups.pop_high();

    …​ // prints the separator, then g digits
}

7.10. Class reverse_digits_groups

The class reverse_digits_groups aims to be used in loops that print groups of digits separated by the thousand separator from the most to the least significant.

namespace strf {
class reverse_digits_groups {
public:
    constexpr static unsigned grp_max = digits_grouping::grp_max;
    constexpr static unsigned grps_count_max = digits_grouping::grps_count_max;

    constexpr reverse_digits_groups() noexcept;
    constexpr reverse_digits_groups(const reverse_digits_groups&) noexcept;
    constexpr bool operator==(const reverse_digits_groups& other) const noexcept;
    constexpr bool operator!=(const reverse_digits_groups& other) const noexcept;
    constexpr reverse_digits_groups& operator=(const reverse_digits_groups& other) noexcept;
    constexpr void push_low(unsigned group) noexcept;
    constexpr void pop_high() noexcept;
    constexpr unsigned highest_group() const noexcept;
    constexpr bool empty() const noexcept;
};
} // namespace strf

The meaning of "group" used in reverse_digits_groups is different than in previous classes.

The value returned by reverse_digits_groups::highest_group() is expected to always be the actual number of digits in the group. This why you prior need to pass the total number of digits to digits_distribution::distribute function: so that it can calculate how many digits actually go in each group.

On the other hand, there is no similar need when you create a digits_grouping_iterator object ( digits_distribution::iterator has no parameter ). So the value returned by digits_grouping_iterator::lowers_group() may actually be larger than the amount of remaining digits to print.

constexpr unsigned highest_group() const noexcept;

Return the actual number of digits in the current group.

Postconditions

The return value is zero when empty() returns true. Otherwise, it is non-zero and not greater than grp_max;

constexpr void pop_high() noexcept;
Effects

None when empty() returns true. Otherwise, moves the return value of highest_group() to the next (less significant) group.

8. Character encodings

8.1. Enumeration charset_id

namespace strf {
enum class charset_id : unsigned { };

constexpr charset_id  scid_ascii        = /* ... */;
constexpr charset_id  scid_utf8         = /* ... */;
constexpr charset_id  scid_utf16        = /* ... */;
constexpr charset_id  scid_utf32        = /* ... */;
constexpr charset_id  scid_iso_8859_1   = /* ... */;
constexpr charset_id  scid_iso_8859_2   = /* ... */;
constexpr charset_id  scid_iso_8859_3   = /* ... */;
constexpr charset_id  scid_iso_8859_4   = /* ... */;
constexpr charset_id  scid_iso_8859_5   = /* ... */;
constexpr charset_id  scid_iso_8859_6   = /* ... */;
constexpr charset_id  scid_iso_8859_7   = /* ... */;
constexpr charset_id  scid_iso_8859_8   = /* ... */;
constexpr charset_id  scid_iso_8859_9   = /* ... */;
constexpr charset_id  scid_iso_8859_10  = /* ... */;
constexpr charset_id  scid_iso_8859_11  = /* ... */;
constexpr charset_id  scid_iso_8859_13  = /* ... */;
constexpr charset_id  scid_iso_8859_14  = /* ... */;
constexpr charset_id  scid_iso_8859_15  = /* ... */;
constexpr charset_id  scid_iso_8859_16  = /* ... */;

constexpr charset_id  scid_windows_1250 = /* ... */;
constexpr charset_id  scid_windows_1251 = /* ... */;
constexpr charset_id  scid_windows_1252 = /* ... */;
constexpr charset_id  scid_windows_1253 = /* ... */;
constexpr charset_id  scid_windows_1254 = /* ... */;
constexpr charset_id  scid_windows_1255 = /* ... */;
constexpr charset_id  scid_windows_1256 = /* ... */;
constexpr charset_id  scid_windows_1257 = /* ... */;
constexpr charset_id  scid_windows_1258 = /* ... */;

} // namespace strf

8.2. Facet category invalid_seq_notifier_c

namespace strf {
struct invalid_seq_notifier_c {
    static constexpr bool constrainable = false;
    static constexpr invalid_seq_notifier get_default() noexcept {
        return {}
    }
};
} // namespace strf

Class invalid_seq_notifier

namespace strf {

class invalid_seq_notifier {
public:

    using category = invalid_seq_notifier_c;

    typedef void(*notify_fptr)();

    constexpr invalid_seq_notifier() noexcept = default;
    constexpr invalid_seq_notifier(const invalid_seq_notifier&) noexcept = default;

    constexpr explicit invalid_seq_notifier(notify_fptr) noexcept;
    constexpr invalid_seq_notifier& operator=(notify_fptr) noexcept;
    constexpr invalid_seq_notifier& operator=(const invalid_seq_notifier& other) noexcept;
    constexpr bool operator==(const invalid_seq_notifier& other) noexcept;
    constexpr operator bool() const noexcept;
    constexpr void notify() const;

private:
    notify_fptr notify_func_ = nullptr; // exposition only
};

} // namespace strf
constexpr invalid_seq_notifier() noexcept;

Trivial default constructor

Poscondition

notify_func_ == nullptr

constexpr invalid_seq_notifier(const invalid_seq_notifier& other) noexcept;

Trivial copy constructor

Poscondition

notify_func_ == other.notify_func_

constexpr explicit invalid_seq_notifier(notify_fptr fptr) noexcept;
Poscondition

notify_func_ == fptr

constexpr invalid_seq_notifier& operator=(const invalid_seq_notifier& other) noexcept;
Poscondition

notify_func_ == other.notify_func_

constexpr bool operator==(const invalid_seq_notifier& other) noexcept;
Return value

notify_func_ == other.notify_func_

constexpr operator bool() const noexcept;
Return value

notify_func_ != nullptr

constexpr void notify() const noexcept;
Effect

Calls notify_func_ if it is not null.

8.3. Facet category surrogate_policy_c

enum class surrogate_policy : bool { strict = false, lax = true };

struct surrogate_policy_c {
    static constexpr bool constrainable = false;
    static constexpr surrogate_policy get_default() noexcept {
        return surrogate_policy::strict;
    }
};

template <>
class facet_traits<surrogate_policy> {
public:
    using category = surrogate_policy_c;
    static constexpr bool store_by_value = true;
};

Semantics

This facet enables you to choose whether a nonconformant presence of a surrogate character shall be treated as invalid.

8.4. Facet category template charset_c

namespace strf {

template <typename CharT>
struct charset_c {
    static constexpr bool constrainable = false;
    static constexpr utf<CharT> get_default() noexcept;
};

template <typename CharT, charset_id CSId>
struct facet_traits<static_charset<CharT, CSId>>
{
    using category = charset_c<CharT>;
};

template <typename CharT>
struct facet_traits<dynamic_charset<CharT>>
{
    using category = charset_c<CharT>;
};
} // namespace strf

For a type to be a facet of charset_c<CharT> it has to be a Charset type for CharT. The library provides two class templates that satisfy that: static_charset and dynamic_charset

8.5. Aliases for pointers to functions

constexpr std::size_t invalid_char_len = (std::size_t)-1;

template <typename SrcCharT, typename DestCharT>
using transcode_f = void (*)
    ( basic_outbuff<DestCharT>& ob
    , const SrcCharT* src
    , std::size_t src_size
    , invalid_seq_notifier inv_seq_notifier
    , surrogate_policy surr_poli );

template <typename SrcCharT>
using transcode_size_f = std::size_t (*)
    ( const SrcCharT* src
    , std::size_t src_size
    , surrogate_policy surr_poli );

template <typename CharT>
using write_replacement_char_f = void(*)( basic_outbuff<CharT>& );

using validate_f = std::size_t (*)(char32_t ch);

using encoded_char_size_f = std::size_t (*) (char32_t ch);

template <typename CharT>
using encode_char_f = CharT*(*) (CharT* dest, char32_t ch);

template <typename CharT>
using encode_fill_f = void (*)
    ( basic_outbuff<CharT>&
    , std::size_t count
    , char32_t ch );

struct codepoints_count_result {
    std::size_t count;
    std::size_t pos;
};

template <typename CharT>
using codepoints_fast_count_f = codepoints_count_result (*)
    ( const CharT* src
    , std::size_t src_size
    , std::size_t max_count );

template <typename CharT>
using codepoints_robust_count_f = codepoints_count_result (*)
    ( const CharT* src
    , std::size_t src_size
    , std::size_t max_count
    , surrogate_policy surr_poli );

template <typename CharT>
using decode_unit_f = char32_t (*) ( CharT );

template <typename SrcCharT, typename DestCharT>
using find_transcoder_f = dynamic_transcoder<SrcCharT, DestCharT> (*)
    ( charset_id );

8.6. Type requirement Transcoder

Given

  • SrcCharT, one of the types: char, char8_t, char16_t, char32_t or wchar_t

  • DestCharT, one of the types: char, char8_t, char16_t, char32_t or wchar_t

  • X, a Transcoder type from SrcCharT to DestCharT

  • x, an expression of type X or const X

  • dest, an lvalue reference of type basic_outbuff<DestCharT>

  • src, a value of type const SrcCharT*

  • src_size, a value of type std::size_t equal to the size of the array pointed by src

  • inv_seq_notifier, a value of type invalid_seq_notifier

  • surr_poli, a value of type surrogate_policy

The following must hold:

x.transcode_size(src, src_size, surr_poli)
Return type

std::size_t

Return value

The number of character that x.transcode(dest, src, src_size, invalid_seq_notifier{}, surr_poli) would write into dest, or a value a greater than that if such exact calculation is difficult ( but ideally not much greater ).

Precondition

x.transcode_func() != nullptr is true

x.transcode(dest, src, src_size, inv_seq_notifier, surr_poli)
Effect

Converts the content of src from one encoding to another writing the result to dest. Each sequence in src that is invalid is translated instead by the replacement character ( that is returned by x.replacement_char() ). And each time that happens, inv_seq_notifier.notify() shall be called if the value of (bool)inv_seq_notifier is true. A sequence in src is considered invalid if it is non-conformant to its corresponding encoding or would cause content written in dest to be non-conformant to the destination encoding, unless such non-conformity is due to a surrogate character and the value of surr_poli is surrogate_policy::lax.

Precondition

x.transcode_func() != nullptr is true

Postconditions

dest.recycle() is not called() if dest.space() >= x.transcode_size(src, src_size, surr_poli) is true.

x.transcode_size_func()
Return type

transcode_size_f<SrcCharT>

Return value

A function pointer such that x.transcode_size_func() (src, src_size, surr_poli) has the same effect as x.transcode_size(src, src_size, surr_poli).

x.transcode_func()
Return type

transcode_f<SrcCharT, DestCharT>

Return value

A function pointer such that x.transcode_func() (dest, src, src_size, inv_seq_notifier, surr_poli) has the same effect as x.transcode(dest, src, src_size, inv_seq_notifier, surr_poli).


Definition

A null transcoder is an object of an Transcoder type where the transcode_func function returns nullptr.

There are two class templates that satisfy Transcoder: static_transcoder and dynamic_transcoder.

8.7. Type requirement Charset

An object whose type is a Charset represents a character encoding. In this documentation the term charset is used interchangeably with encoding and character encoding.

Given

  • CharT, one of the follwoing types: char, char8_t, char16_t, char32_t or wchar_t

  • X, a Charset type for type CharT

  • x, an expression of type X or const X

  • OtherCharT, one of the folowing types : char, char8_t, char16_t or wchar_t

  • ptr, a value of type CharT*

  • src, a value of type const CharT*

  • src_size, a value of type std::size_t equal to the size of the array pointed by src

  • count, a value of type std::size_t

  • max_count, a value of type std::size_t

  • ch32, a value of type char32_t

  • ch, a value of type CharT

  • ob, an lvalue reference of type basic_outbuff<CharT>

  • cs_id, value of type charset_id

The following must hold:

X::code_unit

Type alias to CharT

x.id()
Return type

charset_id

Return value

The charset_id that corresponds to this encoding.

x.name()
Return type

const char*

Return value

The name of this encoding. Examples: "UTF-8", "ASCII", "ISO-8859-1", "windows-1252".

x.replacement_char()
Return type

char32_t

Return value

The character used to signalize an error. Usually it is the replacement character � if it is supported by this encoding, or the question mark '?' otherwise.

x.write_replacement_char(ob)
Return type

Writes into ob the codepoint returned by x.replacement_char() encoded in this charset.

x.replacement_char_size()
Return type

std::size_t

Return value

The number of characters that x.write_replacement_char(ob) writes into ob.

x.encoded_char_size(ch32)
Return type

std::size_t

Return value

The size of the string containing the UTF-32 character ch32, if ch32 is supported in this encoding. Otherwise, x.replacement_char_size().

Postcondition

The return value must be greater than zero.

Note

This function does not check whether ch32 is a legal code point, only if it is possible to write it in this encoding. For example, if this is encoding is UTF-32, this function considers as valid any value for ch32 ( even if is is greater than 0x10FFFF ). Surrogates characters are also not sanitized.

x.validate(ch32)
Return type

std::size_t

Return value

The size of the string containing the UTF-32 character ch32, if ch32 is supported in this encoding. Otherwise, (std::size_t)-1.

Postcondition

The return value must be greater than zero.

x.encode_char(ptr, ch32)
Effect

Writes into ptr the UTF-32 character ch32 encoded into this encoding, adopting the policy of surrogate_policy::lax, i.e. if ch32 is a surrogate, treat it as if it were a valid codepoint. If this encoding is not able to encode ch32, then encode instead the return of x.replacement_char().

Return type

CharT*

Postcondition

x.encode_char(ptr, ch32) - ptr == x.encoded_char_size(ch32) is true.

Return value

The position just after the last writen character.

Note

This function does not check whether ch32 is a legal code point, only if it is possible to write it in this encoding. For example, if this is encoding is UTF-32, this function considers as valid any value for ch32 ( even if is is greater than 0x10FFFF ). Surrogates characters are also not sanitized.

x.encode_fill(ob, count, ch32)
Effect

Writes count times into ob the UTF-32 character ch32 encoded into this encoding, if it is supported. Otherwise writes x.replacement_char() instead.

Return type

void

Note

encode_fill does not check whether ch32 is a legal code point, only if it is possible to write it in this encoding. For example, if this is encoding is UTF-32, encode_fill considers as valid any value for ch32 ( even if is is greater than 0x10FFFF ). Surrogates characters are also not sanitized.

x.codepoints_fast_count(src, src_size, max_count)
Return type

codepoints_count_result

Return value

{c, pos}, where:

  • c is the number of Unicode code points in src, if such value is less than max_count. Otherwise, c is equal to max_count.

  • pos is the greatest value not greater than src_size such that x.codepoints_fast_count(src, pos, (std::size_t)-1).count is equal to c.

Posconditions
  • c <= max_count is true

  • pos <= src_size is true

Note

If the input is non-conformant to the corresponding character encoding, this function may return an incorrect value. For instance, for UTF-8 this function may simply count the bytes that are not continuation bytes.

x.codepoints_robust_count(src, src_size, max_count, surr_poli)
Effect

Counts the codepoints until is equal to max_count.

Return type

codepoints_count_result

Return value

{c, pos}, where:

  • c is equal to std::min(max_count, u32len), where u32len is the length of the UTF-32 string that would be generated by converting src from this encoding to UTF-32, according to surr_poli.

  • pos is the greatest value not greater than src_size such that x.codepoints_robust_count(src, pos, (std::size_t)-1, surr_poli).count is equal to c.

Posconditions
  • c <= max_count is true

  • pos <= src_size is true

x.decode_unit(ch)
Effect

Decodes ch from this encoding to UTF-32 assuming the policy of surrogate_policy::lax. If ch is an invalid character, returns U'\uFFFD'.

Return type

char32_t

x.encode_char_func()
Return type

encode_char_f<CharT>

Return value

A function pointer such that x.encode_char_func() (ch32) has the same effect as x.encode_char(ch32).

x.encode_fill_func()
Return type

encode_fill_f<CharT>

Return value

A function pointer such that x.encode_fill_func() (ob, count, ch32) has the same effect as x.encode_fill(ob, count, ch32).

x.write_replacement_char_func()
Return type

write_replacement_char_f<CharT>

Return value

A function pointer such that x.write_replacement_char_func() (ob) has the same effect as x.write_replacement_char(ob)

x.validate_func()
Return type

validate_f

Return value

A function pointer such that x.validate_func() (ch32) returns the same value as x.validate(ch32)

x.from_u32()
Return type

A Transcoder from char32_t to CharT

Return value

A transcoder that converts UTF-32 to this encoding.

x.to_u32()
Return type

A Transcoder from CharT to char32_t

Return value

A transcoder that converts this encoding to UTF-32.

x.sanitizer()
Return type

A Transcoder from CharT to CharT

Return value

A transcoder that "converts" this encoding to this encoding, i.e. a sanitizer of this encoding.

( Optional )
x.find_transcoder_to(tag<OtherCharT>, cs_id)
Return type

dynamic_transcoder<CharT, OtherCharT>

Return value

A transcoder that converts this encoding to the encoding corresponding to cs_id, or an null transcoder.

( Optional )
x.find_transcoder_from(tag<OtherCharT>, cs_id)
Return type

dynamic_transcoder<OtherCharT, CharT>

Return value

A transcoder that converts the encoding corresponding to cs_id to this encoding, or an null transcoder.

You shall not create an Charset for char32_t, since char32_t is reserved for UTF-32. The library internaly assumes in many occasions that the encoding is UTF-32 when CharT is char32_t.

8.8. Class template static_transcoder

template <class SrcCharT, class DestCharT, charset_id Src, charset_id Dest>
class static_transcoder;

// sanitizers
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_ascii, scid_ascii>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_1, scid_iso_8859_1>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_2, scid_iso_8859_2>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_3, scid_iso_8859_3>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_4, scid_iso_8859_4>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_5, scid_iso_8859_5>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_6, scid_iso_8859_6>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_7, scid_iso_8859_7>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_8, scid_iso_8859_8>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_9, scid_iso_8859_9>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_10, scid_iso_8859_10>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_11, scid_iso_8859_11>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_13, scid_iso_8859_13>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_14, scid_iso_8859_14>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_15, scid_iso_8859_15>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_16, scid_iso_8859_16>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1250, scid_windows_1250>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1251, scid_windows_1251>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1252, scid_windows_1252>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1253, scid_windows_1253>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1254, scid_windows_1254>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1255, scid_windows_1255>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1256, scid_windows_1256>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1257, scid_windows_1257>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1258, scid_windows_1258>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf8, scid_utf8>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf16, scid_utf16>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_utf32>;

// to UTF-32
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_ascii, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_1, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_2, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_3, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_4, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_5, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_6, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_7, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_8, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_9, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_10, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_11, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_13, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_14, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_15, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_iso_8859_16, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1250, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1251, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1252, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1253, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1254, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1255, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1256, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1257, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_windows_1258, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf8, scid_utf32>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf16, scid_utf32>;

// from UTF-32
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_ascii>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_1>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_2>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_3>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_4>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_5>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_6>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_7>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_8>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_9>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_10>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_11>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_13>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_14>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_15>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_iso_8859_16>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1250>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1251>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1252>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1253>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1254>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1255>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1256>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1257>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_windows_1258>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_utf8>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf32, scid_utf16>;

// others
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf8, scid_utf16>;
template <class SrcCharT, class DestCharT>
class static_transcoder<SrcCharT, DestCharT, scid_utf16, scid_utf8>;

static_transcoder class template has no generic implementation. Instead, the library provides the template specializations listed above. All of them are empty classes, and are Transcoder, and their member functions transcode_func and transcode_size_func never return nullptr.

8.9. Class template static_charset

template <class CharT, charset_id>
class static_charset;

template <class CharT> class static_charset<CharT, scid_ascii>;
template <class CharT> class static_charset<CharT, scid_iso_8859_1>;
template <class CharT> class static_charset<CharT, scid_iso_8859_2>;
template <class CharT> class static_charset<CharT, scid_iso_8859_3>;
template <class CharT> class static_charset<CharT, scid_iso_8859_4>;
template <class CharT> class static_charset<CharT, scid_iso_8859_5>;
template <class CharT> class static_charset<CharT, scid_iso_8859_6>;
template <class CharT> class static_charset<CharT, scid_iso_8859_7>;
template <class CharT> class static_charset<CharT, scid_iso_8859_8>;
template <class CharT> class static_charset<CharT, scid_iso_8859_9>;
template <class CharT> class static_charset<CharT, scid_iso_8859_10>;
template <class CharT> class static_charset<CharT, scid_iso_8859_11>;
template <class CharT> class static_charset<CharT, scid_iso_8859_13>;
template <class CharT> class static_charset<CharT, scid_iso_8859_14>;
template <class CharT> class static_charset<CharT, scid_iso_8859_15>;
template <class CharT> class static_charset<CharT, scid_iso_8859_16>;
template <class CharT> class static_charset<CharT, scid_windows_1250>;
template <class CharT> class static_charset<CharT, scid_windows_1251>;
template <class CharT> class static_charset<CharT, scid_windows_1252>;
template <class CharT> class static_charset<CharT, scid_windows_1253>;
template <class CharT> class static_charset<CharT, scid_windows_1254>;
template <class CharT> class static_charset<CharT, scid_windows_1255>;
template <class CharT> class static_charset<CharT, scid_windows_1256>;
template <class CharT> class static_charset<CharT, scid_windows_1257>;
template <class CharT> class static_charset<CharT, scid_windows_1258>;
template <class CharT> class static_charset<CharT, scid_utf8>;
template <class CharT> class static_charset<CharT, scid_utf16>;
template <class CharT> class static_charset<CharT, scid_utf32>;

static_charset class template has no generic implementation. Instead, the library provides the template specializations listed above. All of them are empty classes, and are Charset.

8.10. Class template dynamic_transcoder

namespace strf {

template <class SrcCharT, class DestCharT>
class dynamic_transcoder {
public:
    constexpr dynamic_transcoder() noexcept;

    constexpr dynamic_transcoder
        ( const dynamic_transcoder& other) noexcept = default;

    template <charset_id Src, charset_id Dest>
    constexpr explicit dynamic_transcoder
        ( static_transcoder<Src, Dest> st );

    void transcode
        ( basic_outbuff<DestCharT>& ob
        , const SrcCharT* src
        , std::size_t src_size
        , invalid_seq_notifier inv_seq_notifier
        , surrogate_policy surr_poli ) const;

    std::size_t transcode_size
        ( const SrcCharT* src
        , std::size_t src_size
        , surrogate_policy surr_poli ) const;

    constexpr transcode_f<SrcCharT, DestCharT> transcode_func() const noexcept;
    constexpr transcode_size_f<SrcCharT> transcode_size_func() const noexcept;
};

} // namespace strf
constexpr dynamic_transcoder() noexcept;

Default constructor

Postconditions
  • transcode_func() == nullptr

  • transcode_size_func() == nullptr

constexpr dynamic_transcoder
    ( const dynamic_transcoder& other) noexcept;

Trivial copy constructor

Postconditions
  • transcode_func() == other.transcode_func()

  • transcode_size_func() == other.transcode_size_func()

template <charset_id Src, charset_id Dest>
constexpr explicit dynamic_transcoder
    ( static_transcoder<Src, Dest> other );
Postconditions
  • transcode_func() == other.transcode_func()

  • transcode_size_func() == other.transcode_size_func()

void transcode
    ( basic_outbuff<DestCharT>& ob
    , const SrcCharT* src
    , std::size_t src_size
    , invalid_seq_notifier inv_seq_notifier
    , surrogate_policy surr_poli ) const;
Effect

Calls transcode_func()(ob, src, src_size, inv_seq_notifier, surr_poli)

std::size_t transcode_size
    ( const SrcCharT* src
    , std::size_t src_size
    , surrogate_policy surr_poli ) const;
Effect

Calls transcode_size_func()(src, src_size, surr_poli)

8.11. Struct template dynamic_charset_data

template <class CharT>
struct dynamic_charset_data {
    const char* name;
    charset_id id;
    char32_t replacement_char;
    std::size_t replacement_char_size;
    validate_f validate_func;
    encoded_char_size_f encoded_char_size_func;
    encode_char_f<CharT> encode_char_func;
    encode_fill_f<CharT> encode_fill_func;
    codepoints_fast_count_f<CharT> codepoints_fast_count_func;
    codepoints_robust_count_f<CharT> codepoints_robust_count_func;

    write_replacement_char_f<CharT> write_replacement_char_func;
    decode_unit_f<CharT> decode_unit_func;

    dynamic_transcoder<CharT, CharT> sanitizer;
    dynamic_transcoder<char32_t, CharT> from_u32;
    dynamic_transcoder<CharT, char32_t> to_u32;

    find_transcoder_f<wchar_t, CharT> find_transcoder_from_wchar;
    find_transcoder_f<CharT, wchar_t> find_transcoder_to_wchar;

    find_transcoder_f<char16_t, CharT> find_transcoder_from_char16;;
    find_transcoder_f<CharT, char16_t> find_transcoder_to_char16;

    find_transcoder_f<char, CharT> find_transcoder_from_char;
    find_transcoder_f<CharT, char> find_transcoder_to_char;

#if defined (__cpp_char8_t)
    find_transcoder_f<char8_t, CharT> find_transcoder_from_char8;
    find_transcoder_f<CharT, char8_t> find_transcoder_to_char8;
#else
    void* find_transcoder_from_char8 = nullptr;
    void* find_transcoder_to_char8 = nullptr;
#endif

};

8.12. Class template dynamic_charset

template <class CharT>
class dynamic_charset {
public:

    using code_unit = CharT;

    dynamic_charset(const dynamic_charset& other) = default;

    dynamic_charset
        ( const dynamic_charset_data<CharT>& d );

    dynamic_charset& operator=(const dynamic_charset& other) noexcept;

    bool operator==(const dynamic_charset& other) const noexcept;

    bool operator!=(const dynamic_charset& other) const noexcept;

    void swap(dynamic_charset& other) noexcept;

    const char* name() const noexcept;

    constexpr charset_id id() const noexcept;

    constexpr char32_t replacement_char() const noexcept;

    constexpr std::size_t replacement_char_size() const noexcept;

    constexpr std::size_t validate(char32_t ch) const; // noexcept

    constexpr std::size_t encoded_char_size(char32_t ch) const; // noexcept

    code_unit* encode_char(code_unit* dest, char32_t ch) const; // noexcept

    void encode_fill
        ( basic_outbuff<CharT>& ob, std::size_t count, char32_t ch ) const;

    std::size_t codepoints_fast_count
        ( const code_unit* src, std::size_t src_size
        , std::size_t max_count ) const;

    std::size_t codepoints_robust_count
        ( const code_unit* src, std::size_t src_size
        , std::size_t max_count, surrogate_policy surr_poli ) const;

    void write_replacement_char(basic_outbuff<CharT>& ob) const;

    char32_t decode_unit(code_unit ch) const;

    encode_char_f<CharT> encode_char_func() const noexcept;

    encode_fill_f<CharT> encode_fill_func() const noexcept;

    write_replacement_char_f<CharT> write_replacement_char_func() const noexcept;

    dynamic_transcoder<char32_t, CharT> from_u32() const;

    dynamic_transcoder<CharT, char32_t> to_u32() const;

    dynamic_transcoder<CharT, CharT> sanitizer() const;

    dynamic_transcoder<CharT, wchar_t> find_transcoder_to
        ( tag<wchar_t>, charset_id id) const;

    dynamic_transcoder<wchar_t, CharT> find_transcoder_from
        ( tag<wchar_t>, charset_id id) const;

    dynamic_transcoder<CharT, char16_t> find_transcoder_to
        ( tag<char16_t>, charset_id id) const;

    dynamic_transcoder<char16_t, CharT> find_transcoder_from
        ( tag<char16_t>, charset_id id) const;

    dynamic_transcoder<CharT, char> find_transcoder_to
        ( tag<char>, charset_id id) const;

    dynamic_transcoder<char, CharT> find_transcoder_from
        ( tag<char>, charset_id id) const;

#if defined (__cpp_char8_t)
    dynamic_transcoder<CharT, char8_t> find_transcoder_to
        ( tag<char8_t>, charset_id id) const;

    dynamic_transcoder<char8_t, CharT> find_transcoder_from
        ( tag<char8_t>, charset_id id) const;
#endif

private:

    const dynamic_charset_data* data; // exposition only
};
dynamic_charset(const dynamic_charset& other);

Trivial copy constructor.

Effect

this->data = other.data

dynamic_charset(const dynamic_charset_data<CharT>& d);
Effect

this->data = d

dynamic_charset& operator=(const dynamic_charset& other) noexcept
Effect

this->data = other.data

bool operator==(const dynamic_charset& other) const noexcept;
Return value

this->data == other.data

bool operator!=(const dynamic_charset& other) const noexcept;
Return value

this->data != other.data

void swap(dynamic_charset& other) noexcept;
Effect

Equivalent to std::swap(this->data, other.data)

const char* name() const noexcept;
Return value

this->data->name

constexpr charset_id id() const noexcept;
Return value

this->data->id

constexpr char32_t replacement_char() const noexcept;
Return value

this->data->replacement_char

constexpr std::size_t replacement_char_size() const noexcept;
Return value

this->data->replacement_char_size

constexpr std::size_t validate(char32_t ch) const; // noexcept
Effect

Calls and returns this->data->validate_func(ch).

constexpr std::size_t encoded_char_size(char32_t ch) const; // noexcept
Effect

Calls and returns this->data->encoded_char_size_func(ch).

code_unit* encode_char(code_unit* dest, char32_t ch) const; // noexcept
Effect

Calls and returns this->data->encoded_char_func(ch).

void encode_fill
    ( basic_outbuff<CharT>& ob, std::size_t count, char32_t ch ) const;
Effect

Calls and returns this->data->encode_fill_func(ob, count, ch).

std::size_t codepoints_fast_count
    ( const code_unit* src, std::size_t src_size
    , std::size_t max_count ) const;
Effect

Calls and returns this->data->codepoints_fast_count_func(src, src_size, max_count).

std::size_t codepoints_robust_count
    ( const code_unit* src, std::size_t src_size
    , std::size_t max_count, surrogate_policy surr_poli ) const;
Effect

Calls and returns this->data->codepoints_robust_count_func(src, src_size, max_count, surr_poli).

void write_replacement_char(basic_outbuff<CharT>& ob) const;
Effect

Calls this->data->write_replacement_char_func(ob).

char32_t decode_unit(code_unit ch) const;
Effect

Calls and returns this->data->decode_unit_func(ch).

encode_char_f<CharT> encode_char_func() const noexcept;
encode_fill_f<CharT> encode_fill_func() const noexcept;
Return value

this->data->encode_fill_func.

write_replacement_char_f<CharT> write_replacement_char_func() const noexcept;
Return value

this->data->write_replacement_char_func.

dynamic_transcoder<char32_t, CharT> from_u32() const;
Return value

this->data->from_u32.

dynamic_transcoder<CharT, char32_t> to_u32() const;
Return value

this->data->to_u32.

dynamic_transcoder<CharT, CharT> sanitizer() const;
Return value

this->data->sanitizer.

dynamic_transcoder<CharT, char> find_transcoder_to
    ( tag<char>, charset_id id ) const;
Return value

this->data->transcoder_finder_to_char(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<CharT, char>{}

dynamic_transcoder<char, CharT> find_transcoder_from
    ( tag<char>, charset_id id ) const;
Return value

this->data->transcoder_finder_from_char(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<char, CharT>{}

dynamic_transcoder<CharT, char8_t> find_transcoder_to
    ( tag<char8_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_to_char8(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<CharT, char8_t>{}

dynamic_transcoder<char8_t, CharT> find_transcoder_from
    ( tag<char8_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_from_char8(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<char8_t, CharT>{}

dynamic_transcoder<CharT, char16_t> find_transcoder_to
    ( tag<char16_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_to_char16(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<CharT, char16_t>{}

dynamic_transcoder<char16_t, CharT> find_transcoder_from
    ( tag<char16_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_from_char16(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<char16_t, CharT>{}

dynamic_transcoder<CharT, wchar_t> find_transcoder_to
    ( tag<wchar_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_to_wchar(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<CharT, wchar_t>{}

dynamic_transcoder<wchar_t, CharT> find_transcoder_from
    ( tag<wchar_t>, charset_id id ) const;
Return value

this->data->transcoder_finder_from_wchar(id) if such function pointer is not null. Otherwise returns dynamic_transcoder<wchar_t, CharT>{}

8.13. Function template find_transcoder

template <class SrcCharset, class DestCharset>
auto find_transcoder(SrcCharset src, DestCharset dest);
Requirements

SrcCharset and DestCharset are Charset types.

Return type

A type that is Transcoder

Return value
When find_transcoder returns an null transcoder , you still can use decode_encode and decode_encode_size.

8.14. Function template decode_encode

namespace strf {

template<class SrcCharT, class DestCharT>
void decode_encode
    ( basic_outbuff<DestCharT>& ob
    , transcode_f<SrcCharT, char32_t> to_u32
    , transcode_f<char32_t, DestCharT> from_u32
    , const SrcCharT* src
    , std::size_t src_size
    , invalid_seq_notifier inv_seq_notifier
    , surrogate_policy surr_poli );

} // namespace strf

Converts the content in src to UTF-32 using to_u32, then writes the result to ob using from_u32.

Postcondition

ob.recycle() is not called if ob.space() is not less then the value returned by decode_encode_size(to_u32, size_calc_func, src, src_size, inv_seq_notifier, surr_poli), where size_calc_func is the return value of dest_enc.from_u32().transcode_size_func(), where dest_enc is the Charset object such that the return value of dest_enc.to_u32().transcode_func() is equal to to_u32.

8.15. Function template decode_encode_size

namespace strf {

template<class SrcCharT>
std::size_t decode_encode_size
    ( transcode_f<SrcCharT, char32_t> to_u32
    , transcode_size_f<char32_t> size_calc_func
    , const SrcCharT* src
    , std::size_t src_size
    , invalid_seq_notifier inv_seq_notifier
    , surrogate_policy surr_poli );

} // namespace strf
Return value

The return of size_calc_func called over the UTF-32 content obtained by passing src to to_u32.

8.16. Type aliases for charsets

namespace strf {

template <class CharT>
using ascii_t = static_charset<CharT, scid_ascii>;

template <class CharT>
using iso_8859_1_t = static_charset<CharT, scid_iso_8859_1>;

template <class CharT>
using iso_8859_2_t = static_charset<CharT, scid_iso_8859_2>;

template <class CharT>
using iso_8859_3_t = static_charset<CharT, scid_iso_8859_3>;

template <class CharT>
using iso_8859_4_t = static_charset<CharT, scid_iso_8859_4>;

template <class CharT>
using iso_8859_5_t = static_charset<CharT, scid_iso_8859_5>;

template <class CharT>
using iso_8859_6_t = static_charset<CharT, scid_iso_8859_6>;

template <class CharT>
using iso_8859_7_t = static_charset<CharT, scid_iso_8859_7>;

template <class CharT>
using iso_8859_8_t = static_charset<CharT, scid_iso_8859_8>;

template <class CharT>
using iso_8859_9_t = static_charset<CharT, scid_iso_8859_9>;

template <class CharT>
using iso_8859_10_t = static_charset<CharT, scid_iso_8859_10>;

template <class CharT>
using iso_8859_11_t = static_charset<CharT, scid_iso_8859_11>;

template <class CharT>
using iso_8859_13_t = static_charset<CharT, scid_iso_8859_13>;

template <class CharT>
using iso_8859_14_t = static_charset<CharT, scid_iso_8859_14>;

template <class CharT>
using iso_8859_15_t = static_charset<CharT, scid_iso_8859_15>;

template <class CharT>
using iso_8859_16_t = static_charset<CharT, scid_iso_8859_16>;

template <class CharT>
using windows_1250_t = static_charset<CharT, scid_windows_1250>;

template <class CharT>
using windows_1251_t = static_charset<CharT, scid_windows_1251>;

template <class CharT>
using windows_1252_t = static_charset<CharT, scid_windows_1252>;

template <class CharT>
using windows_1253_t = static_charset<CharT, scid_windows_1253>;

template <class CharT>
using windows_1254_t = static_charset<CharT, scid_windows_1254>;

template <class CharT>
using windows_1255_t = static_charset<CharT, scid_windows_1255>;

template <class CharT>
using windows_1256_t = static_charset<CharT, scid_windows_1256>;

template <class CharT>
using windows_1257_t = static_charset<CharT, scid_windows_1257>;

template <class CharT>
using windows_1258_t = static_charset<CharT, scid_windows_1258>;

template <class CharT>
using utf8_t = static_charset<CharT, scid_utf8>;

template <class CharT>
using utf16_t = static_charset<CharT, scid_utf16>;

template <class CharT>
using utf32_t = static_charset<CharT, scid_utf32>;

template <class CharT>
using utf_t = /* see below */;

} // namespace strf
template <class CharT>
using utf_t = /* ... */;

utf_t<CharT> is an alias to utf8_t<CharT>, utf16_t<CharT> or utf32_t<CharT>, depending on the value of sizeof(CharT).

8.17. Template variable for charsets

namespace strf {

template <class CharT> constexpr ascii_t<CharT>         ascii = {};

template <class CharT> constexpr iso_8859_1_t<CharT>    iso_8859_1 = {};
template <class CharT> constexpr iso_8859_2_t<CharT>    iso_8859_2 = {};
template <class CharT> constexpr iso_8859_3_t<CharT>    iso_8859_3 = {};
template <class CharT> constexpr iso_8859_4_t<CharT>    iso_8859_4 = {};
template <class CharT> constexpr iso_8859_5_t<CharT>    iso_8859_5 = {};
template <class CharT> constexpr iso_8859_6_t<CharT>    iso_8859_6 = {};
template <class CharT> constexpr iso_8859_7_t<CharT>    iso_8859_7 = {};
template <class CharT> constexpr iso_8859_8_t<CharT>    iso_8859_8 = {};
template <class CharT> constexpr iso_8859_9_t<CharT>    iso_8859_9 = {};
template <class CharT> constexpr iso_8859_10_t<CharT>   iso_8859_10 = {};
template <class CharT> constexpr iso_8859_11_t<CharT>   iso_8859_11 = {};
template <class CharT> constexpr iso_8859_13_t<CharT>   iso_8859_13 = {};
template <class CharT> constexpr iso_8859_14_t<CharT>   iso_8859_14 = {};
template <class CharT> constexpr iso_8859_15_t<CharT>   iso_8859_15 = {};
template <class CharT> constexpr iso_8859_16_t<CharT>   iso_8859_16 = {};

template <class CharT> constexpr windows_1250_t<CharT>  windows_1250 = {};
template <class CharT> constexpr windows_1251_t<CharT>  windows_1251 = {};
template <class CharT> constexpr windows_1252_t<CharT>  windows_1252 = {};
template <class CharT> constexpr windows_1253_t<CharT>  windows_1253 = {};
template <class CharT> constexpr windows_1254_t<CharT>  windows_1254 = {};
template <class CharT> constexpr windows_1255_t<CharT>  windows_1255 = {};
template <class CharT> constexpr windows_1256_t<CharT>  windows_1256 = {};
template <class CharT> constexpr windows_1257_t<CharT>  windows_1257 = {};
template <class CharT> constexpr windows_1258_t<CharT>  windows_1258 = {};

template <class CharT> constexpr utf8_t<CharT>          utf8 = {};
template <class CharT> constexpr utf16_t<CharT>         utf16 = {};
template <class CharT> constexpr utf32_t<CharT>         utf32 = {};
template <class CharT> constexpr utf_t<CharT>           utf = {};

} // namespace strf

9. Width Calculation

9.1. Facet category width_calculator_c

namespace strf {

struct width_calculator_c
{
    static constexpr bool constrainable = true;

    static constexpr width_as_u32len get_default() noexcept;
};

} // namespace strf

For a type to be a facet of the width_calculator_c category, it has to satisfy the WidthCalculator requirements.

Type requirement WidthCalculator

Given

  • CharT, one of the types: char, char8_t, char16_t, char32_t or wchar_t

  • CharsetT, a Charset type for type CharT

  • charset, a value of type CharsetT

  • ch a value of type CharT

  • limit, a value of type width_t

  • str, a value of type const CharT* pointing to a string encoded according to charset.

  • str_len, a value of type std::size_t equal to the length of string str.

  • surr_poli, a value of type surrogate_policy

For a type X to be a WidthCalculator, given an object x of type X, the following syntax and requirements have to be satisfied:

X::category

A type alias to width_calculator_c.

x.char_width(charset, ch)
Return type

width_t

Return value

The width of ch when encoded according to charset.

x.str_width(charset, limit, str, str_len, surr_poli)
Return type

width_t

Return value

The width of the string str if it is less than limit. Otherwise, it can be any value that is greater than or equal to limit.

x.str_width_and_pos(charset, limit, str, str_len, surr_poli)
Effect

Calculates the width of str. If such value is less than limit, then calculates the size of the substring of str whose width is equal to limit.

Return type

width_and_pos

Return value

A value ret of type width_and_pos, such that

  • ret.pos is the greatest value that is less than or equal to str_len such that x.width(charset, width_max, str, ret.pos, surr_poli).width is less than or equal to limit.

  • ret.width is the width of the substring of str with size ret.pos that starts at the same position of str.

The library provides three classes and one class template that satisfy WidthCalculator: fast_width, width_as_fast_u32len, width_as_u32len and width_by_func.

Struct width_and_pos

struct width_and_pos {
    width_t width;
    std::size_t pos;
};

9.2. Class fast_width_t

Class fast_width_t is a facet of the category width_calculator_c that evaluates the width of a string as its size.

class fast_width_t final
{
public:
    using category = width_calculator_c;

    template <typename Charset>
    constexpr width_t char_width
        ( Charset
        , typename Charset::code_unit ) const noexcept;

    template <typename Charset>
    constexpr width_t str_width
        ( Charset
        , width_t limit
        , const typename Charset::code_unit*
        , std::size_t str_len
        , surrogate_policy ) const noexcept;

    template <typename Charset>
    width_and_pos str_width_and_pos
        ( Charset
        , width_t limit
        , const typename Charset::code_unit*
        , std::size_t str_len
        , surrogate_policy ) const noexcept;
};

constexpr fast_width_t fast_width {};
template <typename Charset>
constexpr width_t char_width
    ( Charset
    , typename Charset::code_unit ) const noexcept;
Return value

1

template <typename Charset>
constexpr width_t str_width
    ( Charset
    , width_t limit
    , const typename Charset::code_unit*
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value
  • str_len, if str_len is less than or equal to limit.floor()

  • otherwise, limit

template <typename Charset>
width_and_pos str_width_and_pos
    ( Charset
    , width_t limit
    , const typename Charset::code_unit*
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value

The return value ret is such that

  • if limit <= 0 is true, then ret.width and ret.pos are 0;

  • otherwise, if limit.floor() is less than str_len, then ret.width and ret.pos are equal to limit.floor();

  • otherwise, ret.width and ret.pos are equal to str_len.

9.3. Class width_as_fast_u32len_t

Class width_as_fast_u32len_t is a facet of the category width_calculator_c. It evaluates the width of a string as the number of Unicode code points. However, to gain performance, differently from width_as_u32len, it assumes that the string is totally conformant to its encoding. For example, if the charset is UTF-8 then str_width may simply return the number of bytes whose bit pattern does not characterizes it as a continuation byte ( 10xxxxxx ).

class width_as_fast_u32len_t final
{
public:
    using category = width_calculator_c;

    template <typename Charset>
    constexpr width_t char_width
        ( Charset cs
        , typename Charset::code_unit ) const noexcept;

    template <typename Charset>
    width_t str_width
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const noexcept;

    template <typename Charset>
    width_and_pos str_width_and_pos
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const noexcept;
};

constexpr width_as_fast_u32len_t width_as_fast_u32len {};
template <typename Charset>
constexpr width_t char_width
    ( Charset
    , typename Charset::code_unit ) const noexcept;
Return value

1

template <typename Charset>
width_t str_width
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value
template <typename Charset>
width_and_pos str_width_and_pos
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value

The return value ret is such that

  • If limit <= 0 is true, then then ret.width and ret.pos are 0;

  • otherwise, ret.width is equal to ret2.count and ret.pos is equal to cs.codepoints_fast_count(str, str_len, lim).pos

9.4. Class width_as_u32len_t

Class width_as_fast_u32len_t is a facet of the category width_calculator_c. It evaluates the width of a string as the number of Unicode code points, assuming that any non-conformity to its corresponding charset is replaced by one codepoint ( since it should be replaced by the replacement character "\uFFFD" (�) ).

class width_as_u32len_t final
{
public:
    using category = width_calculator_c;

    template <typename Charset>
    constexpr width_t char_width
        ( Charset cs
        , typename Charset::code_unit ) const noexcept;

    template <typename Charset>
    width_t str_width
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const noexcept;

    template <typename Charset>
    width_and_pos str_width_and_pos
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const noexcept;
};

constexpr width_as_u32len_t width_as_u32len = {};
template <typename Charset>
constexpr width_t char_width
    ( Charset
    , typename Charset::code_unit ) const noexcept;
Return value

1

template <typename Charset>
width_t str_width
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value
template <typename Charset>
width_and_pos str_width_and_pos
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy ) const noexcept;
Return value

The return value ret is such that

  • If limit <= 0 is true, then then ret.width and ret.pos are 0;

  • otherwise, ret.width is equal to ret2.count and ret.pos is equal to cs.codepoints_robust_count(str, str_len, lim).pos

9.5. Class template width_by_func

The instances of the width_by_func class template are facets of the category width_calculator_c. It calculates the width of a string by converting it to UTF-32, and then calling the provided function to evaluate the width of each UTF-32 character.

template <typename CharWidthFunc>
class width_by_func{
public:
    using category = width_calculator_c;

    template <typename Charset>
    width_t char_width
        ( Charset cs
        , typename Charset::code_unit ) const;

    template <typename Charset>
    width_t str_width
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const;

    template <typename Charset>
    width_and_pos str_width_and_pos
        ( Charset cs
        , width_t limit
        , const typename Charset::code_unit* str
        , std::size_t str_len
        , surrogate_policy ) const;

private:

    const CharWidthFunc func_; // exposition only
};

Compile-time requirements

Given

  • ch, a value of type char32_t

  • func, a object of type CharWidthFunc or const CharWidthFunc

The expression func(ch) must be well-formed and the return type must be width_t.

Member functions

template <typename Charset>
width_t char_width
    ( Charset cs
    , typename Charset::code_unit ch) const;
Return value

func_(cs.decode_unit(ch))

template <typename Charset>
width_t str_width
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy  surr_poli) const;
Return value

The sum of the values of func_(ch32), where ch32 is each of the char32_t values that would be written into ob — an arbitrary object whose type derives from basic_outbuff<char32_t> — by the call

cs.to_u32().transcode
    ( ob, str, str_len, invalid_seq_notifier{}, surr_poli )

, if such value is less than or equal to limit. Otherwise, the return value can be anyone that is greater than or equal to limit.

template <typename Charset>
width_and_pos str_width_and_pos
    ( Charset cs
    , width_t limit
    , const typename Charset::code_unit* str
    , std::size_t str_len
    , surrogate_policy surr_poli) const;
Return value

The return value ret is such that:

  • ret.width is the sum of the values of func_(ch32), where ch32 is each of the char32_t values that are written into ob by the call

    cs.to_u32().transcode
        ( ob, str, ret.pos, {invalid_seq_policy}::replace, surr_poli )

    , where ob is any object whose type derives from basic_outbuff<char32_t>.

  • ret.pos is the greatest value that is less than or equal to str_len such that str_width_and_pos(cs, limit, str, ret.pos, surr_poli).width is less than or equal to limit.

9.6. Function template make_width_calculator

template <typename CharWidthFunc>
width_by_func<CharWidthFunc> make_width_calculator(CharWidthFunc f);
Return value

width_by_func<CharWidthFunc>{f}

9.7. Class width_t

width_t is an unsigned type that implements Q16.16 arithmetics and is used to represent width of textual content when text alignment formatting is used. The value of width_t(1) corresponds to one en.

namespace strf {

class width_t {
public:
    struct from_underlying_tag{};
    constexpr width_t() noexcept;
    constexpr width_t(std::uint16_t) noexcept;
    constexpr width_t(const width_t&) noexcept;
    constexpr width_t(from_underlying_tag, std::uint32_t) noexcept;

    constexpr width_t& operator=(const width_t& other) noexcept;
    constexpr width_t& operator=(std::uint16_t& x) noexcept;

    constexpr bool operator==(const width_t& other) const noexcept;
    constexpr bool operator!=(const width_t& other) const noexcept;
    constexpr bool operator<(const width_t& other) const noexcept;
    constexpr bool operator>(const width_t& other) const noexcept;
    constexpr bool operator<=(const width_t& other) const noexcept;
    constexpr bool operator>=(const width_t& other) const noexcept;

    constexpr bool is_integral() const noexcept;
    constexpr unsigned floor() const noexcept;
    constexpr unsigned ceil() const noexcept;
    constexpr std::uint16_t round() const noexcept;

    constexpr width_t operator-() const noexcept;
    constexpr width_t operator+() const noexcept;
    constexpr width_t& operator+=(width_t other) noexcept;
    constexpr width_t& operator-=(width_t other) noexcept;
    constexpr width_t& operator*=(std::uint16_t m) noexcept;
    constexpr width_t& operator/=(std::uint16_t d) noexcept;
    constexpr width_t& operator*=(width_t other) noexcept;
    constexpr width_t& operator/=(width_t other) noexcept;

    constexpr std::uint32_t underlying_value() const noexcept;
    constexpr static width_t from_underlying(std::uint32_t) noexcept;

private:
    std::uint32_t _underlying_value; // exposition only
};

constexpr width_t width_max = width_t::from_underlying(UINT32_MAX);

constexpr bool operator==(width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator==(std::uint16_t lhs, width_t rhs) noexcept;
constexpr bool operator!=(width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator!=(std::uint16_t lhs, width_t rhs) noexcept;
constexpr bool operator< (width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator< (std::uint16_t lhs, width_t rhs) noexcept;
constexpr bool operator<=(width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator<=(std::uint16_t lhs, width_t rhs) noexcept;
constexpr bool operator> (width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator> (std::uint16_t lhs, width_t rhs) noexcept;
constexpr bool operator>=(width_t lhs, std::uint16_t rhs) noexcept;
constexpr bool operator>=(std::uint16_t lhs, width_t rhs) noexcept;

constexpr width_t operator+(width_t lhs, width_t rhs) noexcept;
constexpr width_t operator+(std::uint16_t lhs, width_t rhs) noexcept;
constexpr width_t operator+(width_t lhs, std::uint16_t rhs) noexcept;
constexpr width_t operator-(width_t lhs, width_t rhs) noexcept;
constexpr width_t operator-(std::uint16_t lhs, width_t rhs) noexcept;
constexpr width_t operator-(width_t lhs, std::uint16_t rhs) noexcept;
constexpr width_t operator*(width_t lhs, width_t rhs) noexcept;
constexpr width_t operator*(std::uint16_t lhs, width_t rhs) noexcept;
constexpr width_t operator*(width_t lhs, std::uint16_t rhs) noexcept;
constexpr width_t operator/(width_t lhs, width_t rhs) noexcept;
constexpr width_t operator/(std::uint16_t lhs, width_t rhs) noexcept;
constexpr width_t operator/(width_t lhs, std::uint16_t rhs) noexcept;

} // namespace strf

to-do

9.8. width_t literal _w

namespace strf {
namespace width_literal {

template <char...C>
constexpr width_t operator "" _w()

} // namespace width_literal
} // namespace strf

The suffix _w can be aplied in floating-points literals in fixed notations as well as integer literals.

Example
using namespace strf::width_literal;

strf::width_t x = 1.5_w;
x += 0.25_w;
x += 1_w;
assert(x == 2.75_w);

10. Miscellaneous

10.1. The lettercase facet

namespace strf {

enum class lettercase { lower = /*…​*/, mixed = /*…​*/, upper = /*…​*/ };

constexpr lettercase lowercase = lettercase::lower;
constexpr lettercase mixedcase = lettercase::mixed;
constexpr lettercase uppercase = lettercase::upper;

struct lettercase_c {
    static constexpr bool constrainable = true;
    constexpr static lettercase get_default() noexcept
    {
        return lettercase::lower;
    }
};

template <>
struct facet_traits<lettercase> {
    using category = lettercase_c;
};

} // namespace strf

10.2. Type traits

The table below list class templates that satisfy UnaryTypeTrait. They are created to be used in the constrain function template to filter printable types.

is_int_number

matches short, int, long, long long and the corresponding unsigned types

is_char

matches char, char8_t, wchar_t, char16_t, and char32_t

is_string

matches strings.

to-do

10.3. Class template tag

namespace strf {

template <typename... >
struct tag
{
    explicit tag() = default;
};

template <typename T>
struct tag<T>
{
    explicit constexpr STRF_HD tag() noexcept { }
    using type = T;
};

} // namespace strf

10.4. Outbuff writing functions

namespace strf {

template <typename CharT>
void write( basic_outbuff<CharT>& ob
          , const CharT* data
          , std::size_t count );

template <typename CharT>
void write( basic_outbuff<CharT>& ob
          , const CharT* data
          , const CharT* data_end );

void write(basic_outbuff<char>& ob, const char* cstr);

void write(basic_outbuff<wchar_t>& ob, const wchar_t* cstr);

} // namespace strf
template <typename CharT>
void write( basic_outbuff<CharT>& ob
          , const CharT* data
          , const CharT* data_end );
Effect

Writes the the range [ data, data_end ) into ob, calling ob.recycle() as many times as necessary.

template <typename CharT>
void write( basic_outbuff<CharT>& ob
          , const CharT* data
          , std::size_t data_size );
Effect

Equivalent to write(ob, data, data + data_size)

void write( {basic_outbuff}<char>& ob
          , const char* cstr );
Effect

Equivalent to write(ob, cstr, std::strlen(cstr))

void write( basic_outbuff<wchar_t>& ob
          , const wchar_t* wcstr );
Effect

Equivalent to write(ob, wcstr, std::wstrlen(wcstr))