为什么constexpr无法绕过constexpr求值
Why if constexpr fails to bypass constexpr evaluation?
我正在使用宏为类型调度构建一个静态循环。这是我迄今所取得的成就。
#define LOOP(n, f)
static_assert(n <= 8 && "static loop size should <= 8");
do {
if constexpr (n >= 8)
f(std::integral_constant<size_t, n - 8>());
if constexpr (n >= 7)
f(std::integral_constant<size_t, n - 7>());
if constexpr (n >= 6)
f(std::integral_constant<size_t, n - 6>());
if constexpr (n >= 5)
f(std::integral_constant<size_t, n - 5>());
if constexpr (n >= 4)
f(std::integral_constant<size_t, n - 4>());
if constexpr (n >= 3)
f(std::integral_constant<size_t, n - 3>());
if constexpr (n >= 2)
f(std::integral_constant<size_t, n - 2>());
if constexpr (n >= 1)
f(std::integral_constant<size_t, n - 1>());
} while (0);
template <typename T> constexpr size_t tupleSize(T&) { return tuple_size_v<T>; }
int main() {
auto t = std::make_tuple(1, "string", 0.2, 3, 1, 1, 1);
LOOP(tupleSize(t), [&](auto i) { cout << std::get<i>(t) << endl; });
return 0;
}
以及导螺杆连杆https://godbolt.org/z/GcMZI3
问题是,为什么前四个分支的编译失败了?
不要使用宏,而是使用函数模板。if constexpr
通过根据模板的当前实例化丢弃未执行的分支来工作。
template <std::size_t n, typename F>
void loop(F&& f)
{
static_assert(n <= 8 && "static loop size should <= 8");
if constexpr (n >= 8)
f(std::integral_constant<size_t, n - 8>());
if constexpr (n >= 7)
f(std::integral_constant<size_t, n - 7>());
if constexpr (n >= 6)
f(std::integral_constant<size_t, n - 6>());
if constexpr (n >= 5)
f(std::integral_constant<size_t, n - 5>());
if constexpr (n >= 4)
f(std::integral_constant<size_t, n - 4>());
if constexpr (n >= 3)
f(std::integral_constant<size_t, n - 3>());
if constexpr (n >= 2)
f(std::integral_constant<size_t, n - 2>());
if constexpr (n >= 1)
f(std::integral_constant<size_t, n - 1>());
}
用法:
int main() {
constexpr auto t = std::make_tuple(1, "string", 0.2, 3);
loop<tupleSize(t)>([&](auto i) { cout << std::get<i>(t) << endl; });
return 0;
}
godbolt.org上的实时示例
来自cppreference:
如果constexpr-If语句出现在模板化实体内部,并且实例化后条件不依赖于值,则在实例化封闭模板时不会实例化丢弃的语句。
在模板之外,将完全检查丢弃的语句。if constexpr不能替代#if预处理指令
相关文章:
- If语句未被求值C++
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- std::可选::value_or()-惰性参数求值
- c++标准是否指定了运算符&&(内置)的求值顺序?
- 如何使C++编译器遵循与C#在该赋值语句中相同的优先级、关联性和求值顺序
- 我可以在C++中延迟布尔变量的求值吗
- 用作成员构造函数参数的函数的求值顺序
- 为什么递归 constexpr 模板值无法编译?
- 用霍纳方法进行多项式求值的C++ constexpr
- constexpr求值的分支/constexpr的重载
- 是否可以测试constexpr函数是否在编译时求值
- 为什么constexpr无法绕过constexpr求值
- C++-Static_assert和constexpr函数在运行时求值的能力
- constexpr函数求值可以做尾递归优化吗?
- GCC constexpr lambda in constexpr functions 和编译时求值
- 如何强制constexpr函数在编译时求值
- Clang抱怨在未求值的上下文中没有定义constexpr函数
- Constexpr变量求值
- 什么时候constexpr函数在编译时求值?