A frequent programming task is generating information for the user. Often you have to assemble a string from several parts. Most of the time there is some sort of format string to determine the basic information with some placeholders at the desired position which are substituted with actual values.
A lot of people are using the printf()
family for
outputting. Unfortunately these are not typesafe. And nor are they appropriate for
translations when the positions of the substituted parameters are swapped for
grammatical reasons.
So I decided to implement a typesafe approach which also takes the position of the substituted values into account: each inserted value is converted into its string representation and substitutes the placeholder with the lowest number. Since such a placeholder consists of a percent sign and a single digit there are up to ten substitutions possible.
The built-in methods handle the common data types like int, float or std::string. But it is also easily possible to extend the output capabilities for your own data types. No changes inside the log4sendpp framework are needed, it needn't even be in the log4sendpp namespace.
In the case you don't really want to output the content of an object because it is too complex you may use a default template instead which outputs only the class name. To avoid pontential conflicts these templates must be enabled by setting the macro LOG4SENDPP_ENABLE_DEFAULT_FORMATTER before including the first log4sendpp header file.
It is also possible to reuse already existing streaming operators for
std::basic_ostream
. The macros LOG4SENDPP_OSTREAMABLE
and LOG4SENDPP_OWSTREAMABLE create code for log4sendpp which uses the
standard streaming functions.
This collection of functions is inspired by the QString
class
which is part of the Qt™ framework by
Trolltech.
class Person { public: Person(std::string in_name, unsigned in_age) : name(in_name) , age(n_age) {} String toString() const { String ret; ret << name << "(" << age << ")"; return ret; } private: std::string name; unsigned age; }; String & operator<< (String &formatter, const Person &pers) { formatter << pers.toString(); return formatter; } class AnotherPerson : public Person { // .. }; std::ostream & operator<< (std::ostream &os, const AnotherPerson &pers) { os << pers.toString(); return os; } LOG4SENDPP_OSTREAMABLE(AnotherPerson) Person pers("Bob", 6); AnotherPerson otherpers("Alice", 7); String format = "%5 and %4 say: %3 plus %2 gives %1"; format << "three" << "two" << "one" << pers << otherpers; std::cout << format << std::endl;