ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
No Matches
PropertyFormatters< TFormattable, TVariable > Class Template Reference


template<typename TFormattable, typename TVariable>
class alib::lang::format::PropertyFormatters< TFormattable, TVariable >


This template class provides a map of PropertyFormatter objects that use format strings which are defined by variables of a Configuration .

The use case is about having different versions of how an object is formatted and to have these versions configurable to end users through the ALib configuration system.


The concept is best explained by a code sample. From the documentation of class PropertyFormatter , we are using the sample setup:

enum class Hobbies
struct Person
String Name;
int Age;
Hobbies Hobby;
Box getName ( const Box& p, AString& ) { return p.Unbox<Person*>()->Name; }
Box getAge ( const Box& p, AString& ) { return p.Unbox<Person*>()->Age; }
Box getHobby ( const Box& p, AString& ) { return p.Unbox<Person*>()->Hobby == Hobbies::Hacking
? A_CHAR("hacking") : A_CHAR("fine arts") ; }
{ A_CHAR("name") , 1, getName },
{ A_CHAR("age") , 1, getAge },
{ A_CHAR("hobby") , 1, getHobby },

Three different output formats, Short, Default and All should be supported We define an enumeration type for this purpose and use macro ALIB_ENUMS_ASSIGN_RECORD to equip the enumeration with ALib Enum Records of type VariableDecl . In addition, macro ALIB_RESOURCED is used to announce that the record data is defined using resourced string data.

enum class PersonFormats
ALIB_RESOURCED( PersonFormats, &alib::BASECAMP.GetResourcePool(),
alib::BASECAMP.ResourceCategory, "PersonFormats" )

The following piece of code is to be performed during bootstrapping. We take the freedom to use the resource pool of module BaseCamp :

alib::BASECAMP.GetResourcePool().BootstrapBulk( alib::BASECAMP.ResourceCategory,
// Enum records for enum class "PersonFormats"
"PersonFormats", A_CHAR( "0,FORMATS," "SHORT" ",,," ","
"1,FORMATS," "DEFAULT" ",,," ","
"2,FORMATS," "ALL" ",,," ),
// Built-in default values for the variables
"PersonFormats_D0", A_CHAR( "{@name}") ,
"PersonFormats_D1", A_CHAR( "{@name} ({@age})") ,
"PersonFormats_D2", A_CHAR( "{@name} aged {@age} loves {@hobby}" ),
// Variable comments. These are written for example to an INI-file if the application
// fetches default values at the end of the process. In this sample, all variables share
// the same comment.
"PersonFormats_C0", A_CHAR( "Short output format for lists of \"Persons\"." ),
"PersonFormats_C1", A_CHAR( "Default output format for lists of \"Persons\"." ),
"PersonFormats_C2", A_CHAR( "Verbose output format for lists of \"Persons\"." ),
nullptr // End marker für method BootstrapBulk (must be given!)
The default value and variable comment string would be saved when we write back the variables to a configuration file. This hints users to the fact that the output format is changeable, i.e. when they open an INI-file. See Configuration::FetchFromDefault for information about how to write built-in default variables like this to an external configuration file.

In the next phase of bootstrapping, our enumeration records have to be initialized from the resource pool:

With this in place, the PropertyFormatters can be created and method Format can be used:

alib::PropertyFormatters<Person, PersonFormats> PersonFormatterMap( PersonCallbacks,
alib::BASECAMP.GetConfig() );

But we're still not fully done yet: The next goal is to have a lightweight object that is "appendable " to objects of class AString . Such object is given with template type PropertyFormatterMapAppendable . It is a simple helper struct that holds a reference to the formatter map, the format enumeration value and the object to format.
We define a shortcut to the type with the right template arguments in place:

Now, we are set and can start using the formatter:

// Our data objects
Person sue= { A_CHAR("Sue") , 28, Hobbies::Hacking };
Person john= { A_CHAR("John"), 35, Hobbies::Hacking };
// format the two data objects
AString target;
target << FMTPerson( PersonFormatterMap, PersonFormats::Short, sue ) << NewLine();
target << FMTPerson( PersonFormatterMap, PersonFormats::All, john ) << NewLine();
std::cout << target;

Running the code above produces the following output:

John aged 35 loves hacking

To make the code even shorter, macros may be used:

// Define custom macros
#define FMT_PERSON(o,p) FMTPerson( PersonFormatterMap, o , p )
#define FMT_PERSON_DEFAULT(p) FMTPerson( PersonFormatterMap, PersonFormats::Default, p )
#define FMT_PERSON_SHORT(p) FMTPerson( PersonFormatterMap, PersonFormats::Short , p )
#define FMT_PERSON_ALL(p) FMTPerson( PersonFormatterMap, PersonFormats::All , p )
// Using the macros
target << FMT_PERSON( PersonFormats::Short, sue ) << NewLine();
target << FMT_PERSON_SHORT( sue ) << NewLine();
target << FMT_PERSON_DEFAULT( sue ) << NewLine();
target << FMT_PERSON_ALL( sue ) << NewLine();
std::cout << target;

The output is:

Sue (28)
Sue aged 28 loves hacking

Using The Appendable With Formatters

The sample above showcased how to append a lightweight object of helper class PropertyFormatterMapAppendable to objects of class AString . A final step is to define the boxing interface FAppend to make boxed objects of our helper type applicable. As the type itself is already appendable, we can use a built-in simple macro for that:

As described in the namespace documentation of module ALib Boxing , such interface definition should be done only once and be placed in the bootstrap section of a software.

With this, using formatters in combination with our helper struct works fine:

->Format( target, "The person is: {}", FMT_PERSON_DEFAULT( john ) )
std::cout << target << endl;

This code produces the following output.

The person is: John (35)

Module Dependencies

This class is only available if module ALib Configuration is included in the ALib Distribution .

Reference Documentation

Template Parameters
TFormattableThe type that is formatted.
TVariableThe enumeration of variables which defines the format strings.

Definition at line 142 of file propertyformatters.hpp.

#include <propertyformatters.hpp>

Collaboration diagram for PropertyFormatters< TFormattable, TVariable >:

Public Field Index:

SPFormatter Formatter

Public Method Index:

 PropertyFormatters (typename PropertyFormatter::TCallbackTable &callbackTable, config::Configuration &configuration, SPFormatter formatter=nullptr)
 ~PropertyFormatters ()
void Format (AString &target, TVariable option, TFormattable &formattable)

Field Details:

◆ callbacks

template<typename TFormattable , typename TVariable >
PropertyFormatter::TCallbackTable& callbacks

The callback table for the property formatters (as given in the constructor).

Definition at line 146 of file propertyformatters.hpp.

◆ config

template<typename TFormattable , typename TVariable >
config::Configuration& config

The configuration used to load (and store the default) format strings from.

Definition at line 149 of file propertyformatters.hpp.

◆ Formatter

template<typename TFormattable , typename TVariable >
SPFormatter Formatter

The formatter (as given in the constructor).

Definition at line 158 of file propertyformatters.hpp.

◆ formatters

template<typename TFormattable , typename TVariable >
std::unordered_map<TVariable, PropertyFormatter*> formatters

The map of formatters

Definition at line 152 of file propertyformatters.hpp.

◆ tempVar

template<typename TFormattable , typename TVariable >
Variable tempVar

A temporary variable to be reused (allocate once pattern).

Definition at line 155 of file propertyformatters.hpp.

Constructor(s) / Destructor Details::

◆ PropertyFormatters()

template<typename TFormattable , typename TVariable >
PropertyFormatters ( typename PropertyFormatter::TCallbackTable & callbackTable,
config::Configuration & configuration,
SPFormatter formatter = nullptr )

Constructor storing arguments in fields. All default values of the variables are stored in the configuration and thus - if the configuration is write enabled - can be noted by the end-user to be configurable.

Parameter formatter defaults to nullptr, which causes this constructor to create a clone of the formatter returned by Formatter::GetDefault . Note, that this is in contrast to the similar parameter of class PropertyFormatter , which uses the default formatter itself in the case that nullptr is provided. The rationale behind creating a copy is that it is quite likely that the PropertyFormatter objects created here are used nested within other format operations. This is especially true with the use of helper struct PropertyFormatterMapAppendable . Now, nested formatting must not be done with the same formatter object.

callbackTableThe callback table as specified with PropertyFormatter::TCallbackTable .
configurationThe configuration to load the format strings from (and to store the default values defined by the enum record of TVariable ).
formatterThe underlying formatter. Used for construction of PropertyFormatter s.
Defaults to nullptr which denotes to create a copy of the formatter returned by Formatter::GetDefault .

Definition at line 188 of file propertyformatters.hpp.

Here is the call graph for this function:

◆ ~PropertyFormatters()

template<typename TFormattable , typename TVariable >
~PropertyFormatters ( )

Destructor. Deletes the PropertyFormatter s which got created.

Definition at line 206 of file propertyformatters.hpp.

Method Details:

◆ Format()

template<typename TFormattable , typename TVariable >
void Format ( AString & target,
TVariable option,
TFormattable & formattable )

Chooses or - if not yet available - creates the right PropertyFormatter and invokes its method Format .

targetThe target string to write into.
optionThe user defined formatting option.
formattableThe custom object which is passed to the callback methods to collect the formatter arguments.

Definition at line 221 of file propertyformatters.hpp.

Here is the call graph for this function:

The documentation for this class was generated from the following file: