C では、SFINAE (Substitution Failure Is Not An Error) を使用すると、次のことが可能になります。テンプレート引数のタイプに応じてコードを有効または無効にします。ただし、クラス テンプレートのメンバー関数を扱う場合、SFINAE は期待どおりに動作しないことがよくあります。
問題を示す例を次に示します。
<code class="cpp">#include <type_traits> struct A {}; struct B {}; template <typename T> struct Foo { typename std::enable_if<std::is_same<T, A>::value>::type bar() {} typename std::enable_if<std::is_same<T, B>::value>::type bar() {} };</code>
この例では、Foo は次のように定義します。 2 つのオーバーロードされたメンバー関数 bar()。最初のオーバーロードは T が A の場合に有効になり、2 番目のオーバーロードは T が B の場合に有効になります。ただし、このコードをコンパイルしようとすると、オーバーロードを解決できないことを示すエラー メッセージが表示されます。
このエラーの理由は、SFINAE が 推定された テンプレート引数に対してのみ機能するためです。クラス テンプレートのメンバー関数の場合、テンプレート引数は推定されず、明示的に指定されます。この問題を解決するには、次のいずれかの手法を使用できます:
明示的なテンプレート引数を使用する:
<code class="cpp">struct Foo { void bar(A) {} void bar(B) {} };</code>
メンバー関数内で std::enable_if を使用します:
<code class="cpp">template <typename T> struct Foo { template<typename U = T> typename std::enable_if<std::is_same<U, A>::value>::type bar() {} template<typename U = T> typename std::enable_if<std::is_same<U, B>::value>::type bar() {} };</code>
明示的なクラス テンプレートの特殊化を使用します:
<code class="cpp">template <> struct Foo<A> { void bar() {} }; template <> struct Foo<B> { void bar() {} };</code>
以上がSFINAE がクラス テンプレートのメンバー関数と連携しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。