cout << format("writing %s, x=%s : %d-th step \n") % "toto" % 40.23 % 50;Так и другие, более гибкие способы форматирования, как, например, такой:
cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style.Самая очевидная проблема с printf — это то, что мы должны точно указать размер каждого аргумента. Например, для time_t в одних случаях писать %I64d, а в других %d. У time_t разный размер может быть и на 32-х битной платформе в зависимости от компилятора. И это только один пример. С boost::format такие проблемы исключаются.
Подробнее по всем возможностям можно посмотреть в документации. Но речь сейчас не о возможностях boost::format , а о том как их применить у себя в программе. Мне кажется, что очень удобно было бы, например, писать информацию в лог файл без предварительного форматирования строки на стеке. Т.е. писать вместо:
string msg = str( boost::format("Debug message %s") % some_msg_string ); log( msg );вот такую строку:
log("Debug message %s") % some_msg_string;Добиться этого не сложно. Нужно, всего лишь, перегрузить оператор %. Для этого создадим класс formatted_log_t. А ещё функцию log, которая возвращает экземпляр этого класса. Класс будет содержать в себе экземпляр boost::format.
#include <sstream> #include <boost/format.hpp> #include <iostream> using namespace std; class formatted_log_t { public: formatted_log_t(const wchar_t* msg ) : fmt(msg) {} ~formatted_log_t() { wcout << fmt << endl; } template <typename T> formatted_log_t& operator %(T value) { fmt % value; return *this; } protected: boost::wformat fmt; };Оператор % должен быть шаблонным так как мы не знаем типы форматируемых аргументов. Функция log будет иметь следующий вид:
formatted_log_t log(const wchar_t* msg) { return formatted_log_t( msg ); }На этом месте реализация функции уже является вполне работоспособной. Далее можно добавлять какие-то другие фичи. Например, фильтр по уровню сообщений. Для этого сделаем функцию и класс шаблонными. Вот так:
#include <sstream> #include <boost/format.hpp> #include <iostream> using namespace std; enum log_level_t { LOG_NOTHING, LOG_CRITICAL, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG }; template<int level> class formatted_log_t { public: formatted_log_t(const wchar_t* msg ) : fmt(msg) {} ~formatted_log_t() { // GLOBAL_LEVEL is a global variable and could be changed at runtime if ( level <= GLOBAL_LEVEL ) wcout << fmt << endl; } template <typename T> formatted_log_t& operator %(T value) { fmt % value; return *this; } protected: boost::wformat fmt; }; template <int level> formatted_log_t<level> log(const wchar_t* msg) { return formatted_log_t<level>( msg ); }Применять этот код можно так:
int main () { log<LOG_DEBUG>(L"TEST %3% %2% %1%") % 5 % 10 % L"privet"; return 0; }Работа с логом, наверное, самое очевидно, но только одно из возможных применений синтаксиса boost::format и далее можно развивать эту идею как вам больше нравится.