如果vs constexpr里面的constexpr函数

陳 力*_*陳 力 3 c++ compile-time constexpr if-constexpr

最近,我修改了一些if constexprif我constexpr功能,发现他们仍然正常工作,并能进行评估时,编译时间.这是一个最小的案例:

template<int N>
constexpr bool is_negative()
{
    if constexpr  (N >= 0) return false;
    else  return true; 
}
int main()
{
    constexpr  bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)

live demo

在上面的例子中,N必须在编译时知道因为它是非类型模板参数,所以if constexpr在这里工作正常.然而,这是一个constexpr功能,因此,IIRC,它是可以让即使我更换一个返回值if constexprif:

template<int N>
constexpr bool is_negative()
{
    if  (N >= 0) return false;
    else  return true; 
}
int main()
{
    constexpr  bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)

live demo

cppref来看,所有的要求A constexpr function must satisfy the following requirements:都没有提到if.因此,IIUC,它应该是实现定义的行为if,即使所有相关变量在编译时都已知(is_negative如上所述),constexpr函数是否包含在编译时进行评估.

所以,我的结论是:

  • 在c ++ 17之前,我们没有if constexpr,所以选择是if,这意味着不能保证我们的constexpr函数在编译时得到评估,所有这些都取决于编译器的实现
  • 在c ++ 17之后,if constexpr如果我们想在编译时对constexpr函数进行求值,则首选.

以上都是我个人的想法,也许是重要的错过/误解,随时纠正我.问题仍然没有改变:if并且if constexpr,对于期望在编译时进行评估的constexpr函数应该更好.

参考: - constexpr函数允许什么? - "if constexpr()"与"if()"之间的区别

Nel*_*eal 10

在c ++ 17之前,我们没有constexpr,所以选择if,这意味着它不能保证在编译时得到我们的constexpr函数得到评估,所有都依赖于编译器的实现

if语句不是constexpr这一事实并不意味着它不能在编译时进行评估,作为constexpr表达式的一部分.在您的示例中,v在两种情况下都在编译时进行求值,因为它必须是:它是一个常量表达式.那不是实现定义的.

在c ++ 17之后,如果我们希望constexpr函数在编译时得到评估,那么首选constexpr.

引入Constexpr if语句来解决问题.获得constexpr函数以在编译时进行评估不是那个问题.

这是一个constexpr if需要a而不是简单的例子if(取自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
}
Run Code Online (Sandbox Code Playgroud)

尝试删除constexpr关键字,看看会发生什么(演示).

另外,请注意,您始终可以使用其他方法解决该问题,但if constexpr具有简洁的优点.例如,这是get_value使用标签分派的等效项:

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>{});
}
Run Code Online (Sandbox Code Playgroud)

演示