クラス テンプレートのメンバー関数 SFINAE: 詳細な説明
C の世界では、SFINAE (Substitution Failure Is Not An Error) により、コンパイル中のインスタンス化エラーを防止することによるテンプレートの最適化。ただし、クラス テンプレートのメンバー関数を扱う場合、SFINAE は予期しない動作をする可能性があります。
メンバー関数 SFINAE の問題
次のコードを考えてみましょう:
<code class="cpp">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>
予想に反して、このコードではエラー メッセージが表示されます。 SFINAE は、クラス テンプレート内のメンバー関数に対して意図したとおりに動作しません。
SFINAE と推定されたテンプレート引数
問題の核心は、SFINAE が推定されたテンプレート引数に依存していることにあります。 。これは、テンプレート引数が関数呼び出しから推定される場合にのみ機能します。メンバー関数の場合、テンプレート引数は推定されず、代わりに明示的に提供されます。
推定された引数を使用した解決策
この問題に対処するには、次のようなコード:
<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>
ここで、Foo()(x) を呼び出すと、コンパイラはテンプレートを推定します。引数 T を指定し、x に基づいて正しいオーバーロードを選択します。このアプローチにより、SFINAE が期待どおりに機能できるようになります。
代わりに: 明示的なクラス テンプレートの特殊化
クラスの構造が重要で変更できない場合は、代替ソリューションとして次のような方法があります。明示的なクラス テンプレートの特殊化:
<code class="cpp">template <typename> struct Foo; template <> struct Foo<A> { void bar() {} }; template <> struct Foo<B> { void bar() {} };</code>
ここで、コンパイラは、どの特殊化に基づいてインスタンス化するかを正確に認識します。提供されるタイプ。スペシャライゼーションの選択には SFINAE には依存しません。
以上がSFINAE がクラス テンプレートのメンバー関数で失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。