為什麼要盡量避免在函式簽章中使用 std::enable_if?
std::enable_if 是 C 語言的多功能工具,可以使用以多種方式根據指定條件有條件地定義函數或類別。然而,Scott Meyers 警告不要在函數簽名中使用它。要理解此建議,需要探索 std::enable_if 可用的不同策略及其意義。
實作選項:
<code class="cpp">template<typename T> struct Check1 { template<typename U = T> U read(typename std::enable_if<std::is_same<U, int>::value>::type* = 0) { return 42; } template<typename U = T> U read(typename std::enable_if<std::is_same<U, double>::value>::type* = 0) { return 3.14; } };</code>
<code class="cpp">template<typename T> struct Check2 { template<typename U = T, typename std::enable_if<std::is_same<U, int>::value, int>::type = 0> U read() { return 42; } template<typename U = T, typename std::enable_if<std::is_same<U, double>::value, int>::type = 0> U read() { return 3.14; } };</code>
<code class="cpp">template<typename T> struct Check3 { template<typename U = T> typename std::enable_if<std::is_same<U, int>::value, U>::type read() { return 42; } template<typename U = T> typename std::enable_if<std::is_same<U, double>::value, U>::type read() { return 3.14; } };</code>
首選方法:
最有利的方法是將enable_if放在範本參數中。這種技術在清晰度和多功能性方面都有優勢。
清晰度:
enable_if 子句可以與回傳和參數類型保持不同,從而產生更具可讀性的程式碼。即使使用別名模板來減少混亂,其他方法中的合併子句仍然結合了單獨且不同的概念。
多功能性:
此技術可以通用適用於各種上下文,包括沒有傳回型別的建構子和禁止附加參數的運算子。 SFINAE 是 std::enable_if 條件行為背後的關鍵,僅適用於模板,進一步支援了此方法的通用性。
在回傳類型中避免使用std::enable_if:
在回傳類型中使用std::enable_if 時,關注的不是函式簽名,而是範本特化。出於清晰和一致性的原因,邁耶斯建議不要這種做法。使用enable_if指定傳回類型會導致範本定義和基本範本之間不一致:
<code class="cpp">template<typename T> struct Check4 { typename std::enable_if<std::is_same<T, int>::value, int>::type read() { return 42; } int read() { // error: redeclared without 'typename' return 3.14; // never used } };</code>
成員函數範本與非成員函數範本:
討論的問題和建議適用於成員和非成員函數範本。方法上沒有顯著差異。
以上是為什麼應該避免在函數返回類型中使用“std::enable_if”?的詳細內容。更多資訊請關注PHP中文網其他相關文章!