在C 中,std::enable_if 是一個元函數,允許基於某些約束條件啟用模板。它最近被更簡潔的 std::enable_if_t 取代。但是,當嘗試移植現有程式碼以使用新語法時,一些使用者會遇到意外的重新定義錯誤。
範例程式碼
考慮使用std: 寫的以下程式碼:enable_if:
template<typename T, typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> void f() { } template<typename T, typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> void f() { }
此程式碼成功編譯,具有int 和double 的單獨特化。現在,假設我們想使用std::enable_if_t 語法重寫它:
template<typename T, typename = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
意外錯誤
與預期相反,此更新的程式碼無法編譯,與海灣合作委員會5.2 reporting:
error: redefinition of 'template<class T, class> void g()' void g() { }
解釋
錯誤在於 std::enable_if_t 表示類型,而不是條件。當用作模板參數時,它指定類型約束。在原始 std::enable_if 情況下,第二個範本參數是指標類型,而在 std::enable_if_t 版本中,它成為類型別名。這會產生兩個具有相同類型 (void()) 的不同範本參數。
解決方案
為了避免這種歧義,我們需要確保第二個模板參數表示唯一類型約束。實現此目的的一種方法是使用虛擬模板參數:
template<typename T, typename U = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename U = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
在這種情況下,U 是一個虛擬參數,僅用於區分兩個模板參數。經過此修改,程式碼將成功編譯。
以上是為什麼在範本參數中使用 std::enable_if_t 時會出現重新定義錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!