C++学习——if constexpr

可以把if constexpr理解为编译时if,只有被选中的if constexpr分支才会被实例化。

template<typename T>
void update(T& target){
//...
    if constexpr(is_pod<T>::value){
        simple_and_fast(target);//用于"普通旧数据"
    }else{
        slow_and_safe(target);
    }
//...
}

这里is_pod<T>是一个类型萃取函数,用来说明一个类型是否可以简单拷贝。在C++20引入概念和约束之后,我们就可以使用概念来代替类型萃取函数和低级技术(例如基于enable_if的重载)
if constexpr不是一种文本处理机制,因此不能用来打破常规的语法、类型和作用域规则。

template<typename T>
auto minus(T a,T b)
    -> std::conditional_t<std::is_same_v<T, double>, double, int> {
    if constexpr (std::is_same<T,double>::value){
        if(std::abs(a-b)<0.0001){
            return 0.;
        }else{
            return a - b;
        }
    } else{
        return static_cast<int>(a - b);
    }
}

当实参为整型时一切正常,但当实参类型为double时,除了代码块内部返回结果类型为double,代码块外部的return static_cast<int>(a - b); 依然会正常编译导致出现两个不同的返回类型而报错。
特别注意:if constexpr不支持短路规则。简单举例

template<typename T>
auto any2i(T t)
    -> std::conditional_t<std::is_same_v<T, std::string>, int, T> {
    if constexpr (std::is_same<T, std::string>::value&&T::npos == -1) {
        return atoi(t.c_str());
    }else {
        return t;
    }
}

下面这种写法是错的,因为当 T 不是 std::string 时,T::npos == -1 仍可能被编译,从而导致失败:

if constexpr (std::is_same_v<T, std::string> && T::npos == -1) {
    return std::atoi(t.c_str());
} else {
    return t;
}

正确写法应把条件拆成嵌套的 if constexpr:

// 正确写法
if constexpr (std::is_same_v<T, std::string>) {
    if constexpr (T::npos == -1) {
        return std::atoi(t.c_str());
    }
} else {
    return t;
}

posted @ 2021-05-13 09:52  丸子球球  阅读(2848)  评论(1)    收藏  举报