为何consteval函数中std::array参数可用于static_assert,整数参数却不行?
为什么consteval函数中std::array参数可用于static_assert,而普通整数参数不行?
核心原因在于consteval函数参数能否作为常量表达式,取决于参数的类型特性以及编译器能否在模板定义阶段确定其值的编译期确定性:
对于
ok参数(std::array<int,3>类型):
std::array的大小是模板非类型参数,属于编译期就固定的信息。无论是调用std::ranges::size(ok)还是ok.size(),本质都是读取这个编译期已知的模板参数值。在consteval函数的上下文里,编译器能明确追踪到ok的类型是std::array<int,3>,因此它的size是绝对的编译期常量,完全满足static_assert对常量表达式的要求。对于
not_ok参数(std::integral类型):
尽管consteval函数要求必须在编译期调用,但not_ok是一个值传递的参数。在函数模板的定义阶段,编译器无法保证所有符合std::integral约束的实参都是编译期常量——哪怕你当前调用时传了字面量2,模板本身需要适配所有合法的调用场景。因此not_ok !=5这个表达式无法被编译器认定为“在所有情况下都是常量表达式”,触发static_assert的错误。
如果想让整数参数能用于static_assert,可以将其改为模板非类型参数,比如:
template<std::ranges::input_range T, std::integral U, U not_ok> consteval int assertStuff2(T ok) { static_assert(not_ok != 5); // 此时编译正常 return 0; }
你的代码示例:
// using gcc 13.1 with -std=c++20 #include <array> #include <concepts> #include <iostream> #include <ranges> template<std::ranges::input_range T, std::integral U> consteval int assertStuff2(T ok, U not_ok) { // (1) both compile fine static_assert(std::ranges::size(ok) != 5); static_assert(ok.size() != 5); // (2) compiler error! // "non-constant condition for static assertion: // 'not_ok' is not a constant expression" static_assert(not_ok != 5); return 0; } int main() { std::cout << assertStuff2(std::array<int, 3>{5, 3, 2}, 2); }
内容的提问来源于stack exchange,提问作者NuclearInternets
相关产品推荐
相关产品推荐

