问题描述
最近,我在constexpr函数中将某些if constexpr
修改为if
,发现它们仍然可以正常工作,并且可以在编译时进行评估.这是一个最小的情况:
Recently I modify some if constexpr
into if
in my constexpr functions and found they still work fine and can be evaluated when compile time. Here is a minimum case:
template<int N>
constexpr bool is_negative()
{
if constexpr (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
在上述情况下,由于N
是非类型模板参数,因此必须在编译时知道它,因此if constexpr
在这里可以正常工作.但是,它是一个constexpr函数,因此iirc,即使我将if constexpr
替换为if
:
In the case above, N
must be known at compile time because it is non-type template parameter, so if constexpr
works fine here. However, it is a constexpr function, so, iirc, it is possible to get a return value even though I replace if constexpr
with if
:
template<int N>
constexpr bool is_negative()
{
if (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
从 cppref 中,A constexpr function must satisfy the following requirements:
中的所有要求都不会提if
.因此,对于IIUC,即使所有相关变量在编译时都是已知的(例如上面的is_negative
),constexpr函数是否包含要在编译时求值的if
都应该是实现定义的行为.
From cppref, all of the requirements in A constexpr function must satisfy the following requirements:
don't mention if
. So, IIUC, it should be implementation defined behavior whether constexpr function contain if
to be evaluted at compile time even though all related variable is known at compile time(like is_negative
above).
所以,我的结论是:
- 在c ++ 17之前,我们没有
if constexpr
,所以选择的是if
,这意味着不能保证在编译时对constexpr函数进行求值,而这一切都取决于编译器的实现 - 在c ++ 17之后,如果希望在编译时评估constexpr函数,则首选
if constexpr
.
- Before c++17, we don't have
if constexpr
, so the choice isif
, which means it is not guaranteed to get our constexpr functions get evaluted at compile time, all depend on compiler implementation - After c++17,
if constexpr
is preferred if we want constexpr functions get evaluated at compile time.
以上全部是我的个人想法,也许是一些重要的遗漏/误解,可以随时纠正我.问题仍然没有改变:if
和if constexpr
,对于预期在编译时进行评估的constexpr函数,应优先使用它们.
All above is my personal thoughts, maybe something important missed/misunderstand, feel free to correct me. The question is still unchanged: if
and if constexpr
, which should be prefered for constexpr functions which expected to be evaluated at compile time.
参考:- constexpr函数允许使用什么?-"if constexpr()"之间的差异与"if()"
推荐答案
if语句不是constexpr的事实并不意味着它不能在编译时作为constexpr表达式的一部分进行求值.在您的示例中,在两种情况下v
都在编译时求值,因为它必须是:它是一个常量表达式.这不是实现的定义.
The fact that an if statement is not constexpr does not mean it can't be evaluated at compile time, as part of a constexpr expression. In your example, v
is evaluated at compile time in both cases, because it is required to be: it's a constant expression. That's not implementation defined.
Constexpr if语句用来解决问题.在编译时获取constexpr函数以求值并不是问题.
Constexpr if statements were introduced to solve a problem. Getting constexpr functions to get evaluated at compile time is not that problem.
这里是一个示例,其中需要constexpr if
而不是简单的if
(摘录自 cppreference ):
Here is an example where a constexpr if
is required instead of a simple if
(taken from cppreference):
template <typename T>
auto get_value(T t) {
if constexpr(std::is_pointer_v<T>)
return *t; // deduces return type to int for T = int*
else
return t; // deduces return type to int for T = int
}
尝试删除constexpr
关键字并查看会发生什么情况(演示).
Try removing the constexpr
keyword and see what happens (demo).
此外,请注意,您始终可以使用其他方法解决该问题,但是if constexpr
具有简洁的优点.例如,这是使用标签分派的等效get_value
:
Also, note that you can always solve that problem using other methods, but if constexpr
has the advantage of conciseness. For instance, here's an equivalent get_value
using tag dispatching:
template<typename T>
auto get_value_impl(T t, std::true_type) {
return *t;
}
template<typename T>
auto get_value_impl(T t, std::false_type) {
return t;
}
template<typename T>
auto get_value(T t) {
return get_value_impl(t, std::is_pointer<T>{});
}
这篇关于constexpr函数内部的if vs if constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!