かなり前に書いてから埋もれていたので、載せておきます。
サンプルコード
#include <iostream> #include <cassert> #include <shand/format.hpp> int main() { // variadic bind const std::string s1 = shand::format("%1% %2% %3%", "Hello", "World", 3.14).str(); assert(s1 == "Hello World 3.14"); // bind chain const std::string s2 = shand::format("%1% %2% %3%")("Hello")("World")(3.14).str(); assert(s2 == "Hello World 3.14"); // output stream std::cout << shand::format("%d %s", 123, "abc") << std::endl; // type-safe printf shand::print("%d %s\n", 123, "abc"); // newline printf shand::println("%d %s", 123, "abc"); }
shand/format.hpp
#ifndef SHAND_FORMAT_INCLUDE #define SHAND_FORMAT_INCLUDE #include <boost/format.hpp> namespace shand { template <class CharT, class Traits = std::char_traits<CharT>, class Alloc = std::allocator<CharT> > class basic_formatter { public: typedef boost::basic_format<CharT, Traits, Alloc> format_type; typedef typename format_type::string_type string_type; typedef basic_formatter& result_type; basic_formatter(const CharT* fmt) : fmt_(fmt) {} basic_formatter(const string_type& fmt) : fmt_(fmt) {} template <class T> basic_formatter& operator()(const T& arg) { fmt_ % arg; return *this; } string_type str() const { return fmt_.str(); } template <class CharT2, class Traits2, class Alloc2> friend std::basic_ostream<CharT2, Traits2>& operator<<(std::basic_ostream<CharT2, Traits2>& os, const basic_formatter<CharT2, Traits2, Alloc2>& fmt); template <class T> static basic_formatter& bind(basic_formatter& fmt, const T& x) { return fmt(x); } template <class Head, class... Tail> static basic_formatter& bind(basic_formatter& fmt, const Head& x, const Tail&... xs) { return bind(fmt(x), xs...); } private: format_type fmt_; }; typedef basic_formatter<char> formatter; typedef basic_formatter<wchar_t> wformatter; template <class CharT2, class Traits2, class Alloc2> inline std::basic_ostream<CharT2, Traits2>& operator<<(std::basic_ostream<CharT2, Traits2>& os, const basic_formatter<CharT2, Traits2, Alloc2>& fmt) { return os << fmt.fmt_; } template <class CharT, class Traits, class Alloc> inline basic_formatter<CharT, Traits, Alloc> format(const std::basic_string<CharT, Traits, Alloc>& fmt) { return basic_formatter<CharT, Traits, Alloc>(fmt); } template <class CharT, class Traits, class Alloc, class... Args> inline basic_formatter<CharT, Traits, Alloc> format(const std::basic_string<CharT, Traits, Alloc>& fmt, const Args&... args) { typedef basic_formatter<CharT, Traits, Alloc> format_type; format_type f(fmt); return format_type::bind(f, args...); } template <class CharT> inline basic_formatter<CharT> format(const CharT* fmt) { return basic_formatter<CharT>(fmt); } template <class CharT, class... Args> inline basic_formatter<CharT> format(const CharT* fmt, const Args&... args) { return format<CharT, std::char_traits<CharT>, std::allocator<CharT>, Args...>(fmt, args...); } template <class... Args> inline void print(const std::string& fmt, const Args&... args) { std::cout << format(fmt, args...); } template <class... Args> inline void print(const std::wstring& fmt, const Args&... args) { std::wcout << format(fmt, args...); } template <class CharT, class... Args> inline void print(const CharT* fmt, const Args&... args) { print(std::basic_string<CharT>(fmt), args...); } template <class... Args> inline void println(const std::string& fmt, const Args&... args) { std::cout << format(fmt, args...) << std::endl; } template <class... Args> inline void println(const std::wstring& fmt, const Args&... args) { std::wcout << format(fmt, args...) << std::endl; } template <class CharT, class... Args> inline void println(const CharT* fmt, const Args&... args) { println(std::basic_string<CharT>(fmt), args...); } } // namespace shand #endif // SHAND_FORMAT_INCLUDE