如何在保留字符串字面量编译期尺寸可见性的前提下,包装consteval函数以简化调用?
如何在保留字符串字面量编译期尺寸可见性的前提下,包装consteval函数以简化调用?
咱们先拆解下你遇到的问题:你想把runtime(constFoo(str))简化成outer(str),但直接在普通函数outer里调用consteval函数constFoo时,编译器不认这个调用是常量表达式,所以报错了。核心原因是consteval函数必须在常量表达式上下文里调用,而普通函数里的普通变量赋值不属于这个上下文。
那怎么解决呢?其实改动很小,只要在outer里把constFoo的结果用constexpr变量存起来就行——因为你的outer函数参数是模板化的字符数组(尺寸N是编译期已知的),所以传入的字符串字面量的尺寸完全能被编译器解析,满足consteval的调用要求。
修改后的代码如下:
#include <string> int runtime(int val) { std::string foo = "foo"; // 一些运行时操作 return val + 2; } template <std::size_t N> consteval int constFoo(const char (&data)[N]) { const auto d = data[0]; return N; } template <std::size_t N> int outer(const char (&data)[N]) { // 用constexpr将调用置于常量表达式上下文中 constexpr int val = constFoo(data); return runtime(val); } int main() { auto d = outer("d"); // 现在可以正常编译运行了 }
为什么这样改就行?
constexpr int val强制要求右侧的constFoo(data)是常量表达式,而因为data的尺寸N是模板参数(编译期已知),字符串字面量的内容和尺寸都能在编译期确定,完全符合consteval函数的调用要求。- 这个方案完全符合你的需求:不用把字符串字面量作为模板参数传递,依然保留了编译期尺寸的可见性,而且调用时只需要写
outer("xxx"),完美简化了原来的嵌套调用。
另外你担心“必须把字面量当模板参数”的情况,确实没必要——模板参数N是编译器自动推导的,你只需要像普通函数一样传字符串字面量就行,完全不用手动指定模板参数。
内容来源于stack exchange
相关产品推荐
相关产品推荐

