C では、SFINAE (置換失敗はエラーではありません) を次の目的で使用できます。タイプの特性に基づいてテンプレートの特殊化を条件付きで有効または無効にします。ただし、テンプレートの戻り値の型とテンプレート パラメーターで SFINAE が異なる方法で適用される場合に、一般的な問題が発生します。
次の main 関数を考えてみましょう:
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 条件がデフォルトのテンプレート引数として含まれており、その結果、2 つの同一の関数テンプレートが 2 回定義されます。これにより、コンパイル エラーが発生します。
正しい実装では、SFINAE 条件はテンプレートの戻り値の型の一部として使用されます。これにはテンプレート パラメーターを参照する式が含まれるため、2 つの関数は異なるシグネチャを持ち、SFINAE が意図したとおりに機能できるようになります。
以上がC の SFINAE : 条件付きテンプレートの特殊化のための戻り値の型とパラメータの型?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。