为什么constexpr无法绕过constexpr求值

Why if constexpr fails to bypass constexpr evaluation?

本文关键字:constexpr 求值 为什么      更新时间:2023-10-16

我正在使用宏为类型调度构建一个静态循环。这是我迄今所取得的成就。

#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预处理指令