如何判断函数是否被consteval执行?及区分constexpr函数的编译/运行期调用
判断constexpr函数是编译期还是运行期调用的实现方法
C++20 标准方案:使用 std::is_constant_evaluated()
C++20 开始在 <type_traits> 头文件中提供了 std::is_constant_evaluated() 这个 constexpr 函数,它能直接判断当前代码是否处于编译期常量表达式求值语境:
- 当函数在编译期被调用(比如初始化 constexpr 变量、作为模板参数等),返回
true - 当函数在运行期被调用时,返回
false
直接把它作为 if constexpr 的条件即可实现需求:
#include <type_traits> constexpr auto f() { // 公共执行代码... if constexpr (std::is_constant_evaluated()) { // 仅编译期执行的逻辑 } else { // 仅运行期执行的逻辑 } // 剩余执行代码... }
C++17 及更早版本的替代方案
如果需要兼容 C++20 之前的标准,只能通过编译期特性的技巧实现,以下是两种常见思路:
1. 利用重载与编译期匹配特性
通过构造只能在编译期匹配的函数重载,间接判断求值语境:
#include <type_traits> namespace detail { // 运行期重载:参数为可变参数,编译期无法优先匹配此版本 constexpr bool is_compile_time(...) { return false; } // 编译期重载:仅当参数是编译期常量时会被优先匹配 template <typename T, T Value> constexpr bool is_compile_time(std::integral_constant<T, Value>) { return true; } } constexpr auto f() { // 公共执行代码... if constexpr (detail::is_compile_time(std::integral_constant<int, 0>{})) { // 编译期逻辑 } else { // 运行期逻辑 } // 剩余执行代码... }
原理:编译期求值时,std::integral_constant<int, 0>{} 是常量表达式,编译器会优先匹配模板重载;运行期求值时,编译器无法保证参数为常量,会匹配可变参数版本。
2. 编译器扩展方案(非标准)
GCC、Clang 等编译器提供了 __builtin_constant_p 内置函数,能判断表达式是否为编译期常量,可直接用于条件判断:
constexpr auto f() { // 公共执行代码... if constexpr (__builtin_constant_p(1)) { // 编译期逻辑 } else { // 运行期逻辑 } // 剩余执行代码... }
注意:这是非标准特性,仅在特定编译器下有效,不推荐跨平台项目使用。
内容的提问来源于stack exchange,提问作者shynur
相关产品推荐
相关产品推荐

