很简单,我们将使用以下内容构建一个编译时字符串" %d"
或者对于每种类型,连接一个'\n'
,并去掉前导空格。
首先,我们需要一个类型来用作编译时字符串:
template<char...cs> struct compile_time_string
{static constexpr char str[sizeof...(cs)+1] = {cs...,'\0'};};
template<char...cs>
const char compile_time_string<cs...>::str[sizeof...(cs)+1];
为了防止中间步骤生成无意义的缓冲区,字符串生成器:
template<char...cs> struct compile_time_stringbuilder
{typedef compile_time_string<cs...> string;};
//remove leading spaces from stringbuilder
template<char...cs> struct compile_time_stringbuilder<' ', cs...>
{typedef typename compile_time_stringbuilder<cs...>::string string;};
然后,您需要需要一个函数compile_time_stringbuffer
和一个类型,并返回一个compile_time_stringbuffer
与" %d"
或附加的任何内容。由于我们正在处理类型,所以我什至不需要定义函数。请注意,我的“结束”专业化连接了'\n'
适合你的性格
template<char...cs, class...Ts>
compile_time_stringbuilder<cs...,'\n'> concatenate_compile_time_format_string(compile_time_stringbuilder<cs...>);
template<char...cs, class...Ts>
auto concatenate_compile_time_format_string(compile_time_stringbuilder<cs...>,int,Ts...args)
-> decltype(concatenate_compile_time_format_string(compile_time_stringbuilder<cs...,' ','%','d'>(),args...));
template<char...cs, class...Ts>
auto concatenate_compile_time_format_string(compile_time_stringbuilder<cs...>,const char*,Ts...args)
-> decltype(concatenate_compile_time_format_string(compile_time_stringbuilder<cs...,' ','%','s'>(),args...));
template<char...cs, class...Ts>
auto concatenate_compile_time_format_string(compile_time_stringbuilder<cs...>,double,Ts...args)
-> decltype(concatenate_compile_time_format_string(compile_time_stringbuilder<cs...,' ','%','f'>(),args...));
最后,一个有用且易于使用的界面。
template<class...Ts>
constexpr const char* build_compile_time_format_string()
{
using compile_time_stringbuilder = decltype(concatenate_compile_time_format_string(compile_time_stringbuilder<>(),std::declval<Ts>()...));
using compile_time_string = typename compile_time_stringbuilder::string;
return compile_time_string::str;
}
它的用法如下:
template<class...Args>
void println(Args...args) {
constexpr const char* formatString = build_compile_time_format_string<Args...>();
std::cout << formatString;
}
这是执行证明:http://coliru.stacked-crooked.com/a/16dc0becd3391aaa
完全没有必要,充实起来可能会很有趣compile_time_string
大致匹配的接口const std::string
,沿着这些思路:
template<char...cs> struct compile_time_string
{
static constexpr char str[sizeof...(cs)+1] = {cs...,'\0'};
constexpr size_t size() {return sizeof...(cs);}
constexpr char* begin() {return str;}
constexpr char* end() {return str+sizeof...(cs);}
};