gpt4 book ai didi

用于调用 printf 的 C++11 编译时格式字符串文字构造

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:44:57 25 4
gpt4 key购买 nike

我想做的是创建:

template<Args... args)>
int println(Args...) {
// implementation which calls:
// printf("<string literal format string at compile time>", args...);
// additional perk would be compile time type checking
// I expect to provide a format string for each type by some template
// specialization.
}

我一直在用编译时字符串文字分析两个有趣的工作:

基本上,我或多或少能够静态推断格式所需字符串文字的长度,但仅此而已,因为编译器拒绝将我的工作视为 constexpr。另一个大问题是,当使用上述链接中的 constexpr 字符串时,编译器永远无法推断出结果字符串的大小。

我越努力实现这一点,我的无知就越多地超过了我的热情。如果有任何提示和/或代码示例可以解决执行此类实现时的部分或全部问题,我将不胜感激。

注意:我不是在寻找有关使用不同形式的日志记录(例如通过 cout)的建议。

注意 2:不应使用任何 std::string,因为它们是运行时

注意 3:通常所有类型安全的 printfs 都使用不同的方法,我很熟悉这可以通过多次调用 printf 轻松完成。我想在一次通话中完成。我也知道可以逐步构建缓冲区,但这个问题是关于构建格式字符串的。 :)

更新:基本上代码需要实现的部分是

constexpr const char* formatString = build_compile_time_format_string(args...);
// build_compile_time_format_string(3, "hi", -3.4)
// should evaluate to "%d %s %f"
// or to "%d hi %f"

最佳答案

很简单,我们将构建一个带有 "%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];

并且为了防止中间步骤生成无意义的缓冲区,一个 stringbuilder:

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 和类型的函数,并返回带有 "%d" 或任何附加内容的 compile_time_stringbuffer .由于我们正在处理类型,所以我什至懒得定义函数。请注意,我的“结束”特化为您连接了一个 '\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 的接口(interface)可能会很有趣,如下所示:

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);}
};

关于用于调用 printf 的 C++11 编译时格式字符串文字构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24152042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com