可以把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;
}
}