在C 語言中,SFINAE(替換失敗不是錯誤)可用於根據類型不是錯誤特徵有條件地啟用或停用範本專業化。然而,當 SFINAE 在模板傳回類型和模板參數中套用不同時,會出現一個常見問題。
考慮以下主要函數:
int main() { foo(5); foo(3.4); }
當SFINAE放入模板參數時,如下圖,編譯失敗錯誤:
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> auto foo(T) -> void { std::cout << "I'm an integrer!\n"; } template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> auto foo(T) -> void { std::cout << "I'm a floating point number!\n"; }
但是,此實作可以正常運作:
template<typename T> auto foo(T) -> typename std::enable_if<std::is_integral<T>::value>::type { std::cout << "I'm an integrer!\n"; } template<typename T> auto foo(T) -> typename std::enable_if<std::is_floating_point<T>::value>::type { std::cout << "I'm a floating point number!\n"; }
差異在於C 標準(14.5.6.1) 定義函數範本重載的方式。如果重載範本具有相同的函數名稱、相同的參數數量和相同的參數類型,則它們是等效的。但是,此比較中不考慮預設模板參數。
在錯誤的實作中,SFINAE 條件作為預設模板參數包含在內,導致兩個相同的函數模板定義了兩次。這會觸發編譯錯誤。
在正確的實作中,SFINAE 條件用作模板傳回類型的一部分。由於這涉及引用模板參數的表達式,因此這兩個函數具有不同的簽名,從而允許 SFINAE 按預期運行。
以上是C 中的 SFINAE:條件模板專業化的回傳類型與參數類型?的詳細內容。更多資訊請關注PHP中文網其他相關文章!