写C++程序设计的大作业时,不方便引用外部的库,想传递一些格式化字符串写起来就很麻烦。一般来说使用sprintf
或者std::ostringstream
,但前者一般只支持C原生类型,而后者通常的写法略显繁琐(前者也比较繁琐)。于是便想到了下面的写法:
1 2
| #define format(__stream)\ (dynamic_cast<std::ostringstream & >(std::ostringstream() __stream).str())
|
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12
| namespace crz {
class bad_comparison : public std::logic_error { public: explicit bad_comparison( const std::type_info &from, const std::type_info &to, const char *opt) : std::logic_error(format(<< from.name() << " " << opt << " " << to.name())) {} };
}
|
还可以用变参模板实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| namespace crz {
namespace detail {
template<typename ...Args, typename = typename std::enable_if<sizeof...(Args) == 0>::type> inline std::ostream &__va_output(std::ostream &os, Args &&...args) { return os; } template<typename T, typename ...Args> inline std::ostream &__va_output(std::ostream &os, T &&t, Args &&...args) { os << t; return __va_output(os, std::forward<Args>(args)...); }
}
template<typename ...Args> inline std::string format(Args &&...args) { std::ostringstream os; detail::__va_output(os, std::forward<Args>(args)...); return os.str(); }
}
|
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12
| namespace crz {
class bad_comparison : public std::logic_error { public: explicit bad_comparison( const std::type_info &from, const std::type_info &to, const char *opt) : std::logic_error(format(from.name(), " ", opt, " ", to.name())) {} };
}
|
不过变参模板的实现显然没有之前用宏实现来得简洁。
以上只是个人一时的脑洞,较大的项目还是用fmt等成熟的格式化库为好(或者等有生之年C++20的format落地后用标准库)。