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){
    if constexpr (std::is_same<T,double>::value){
        if(std::abs(a-b)<0.0001){
            return 0.;
        }else{
            return a - b;
        }
    }
    return static_cast<int>(a - b);
}

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

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

如果传入实参类型为std::string,则肯定满足上述条件,但假如传入实参不为std::string,虽然它不满足std::is_same<T, std::string>::value,但由于if constexpr不支持短路规则,所以T::npos == -1依然会被编译。由于T::nops是个非法的表达式所以会编译失败。上述例子正确写法应该是:

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

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