ホームページ  >  記事  >  バックエンド開発  >  SFINAE がクラス テンプレートのメンバー関数で失敗するのはなぜですか?

SFINAE がクラス テンプレートのメンバー関数で失敗するのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-04 22:18:02742ブラウズ

Why Does SFINAE Fail for Class Template Member Functions?

クラス テンプレート メンバー関数で SFINAE が失敗する

テンプレート メタプログラミングで一般的に使用される、代替失敗はエラーではない (SFINAE) メカニズム。クラス テンプレートのメンバー関数に適用すると、特有の動作を示すようです。

問題

次のコード スニペットを考えてみましょう。

<code class="cpp">#include <type_traits>

struct A{};
struct B{};

template <typename T>
struct Foo
{
    // Conditional enable bar() for T == A
    typename std::enable_if<std::is_same<T, A>::value>::type
    bar()
    {}

    // Conditional enable bar() for T == B
    typename std::enable_if<std::is_same<T, B>::value>::type
    bar()
    {}
};</code>

このコードFoo クラス テンプレートで bar() の 2 つのオーバーロードを定義しようとします。SFINAE を使用して、T の値に基づいて各オーバーロードを条件付きで有効にします。ただし、コードは次のエラーでコンパイルに失敗します:

<code class="cpp">error: 'typename std::enable_if<std::is_same<T, B>::value>::type Foo<T>::bar()' cannot be overloaded</code>

説明

SFINAE は通常、テンプレート引数に基づいてテンプレートの特殊化を有効または無効にするために使用されます。ただし、SFINAE は、推定された テンプレート引数、つまりオーバーロードの解決中に自動的に推定される引数にのみ適用されます。メンバー関数の場合、テンプレート引数は推定されず、クラスのインスタンス化時に明示的に指定されます。したがって、SFINAE はメンバー関数には適用できません。

解決策

この問題に対処するには、主に 2 つの方法があります。

  • 関数テンプレートの使用: 以下に示すように、オーバーロードごとに個別の関数テンプレートを定義します:
<code class="cpp">template <typename T>
void bar(Foo<T><- A) {}

template <typename T>
void bar(Foo<T><- B) {}
  • 明示的なクラス テンプレートの特殊化を使用: 個別に定義以下に示すように、各オーバーロードのクラス テンプレート:
<code class="cpp">template <typename> struct Foo;

template <> struct Foo<A> { void bar() {} };
template <> struct Foo<B> { void bar() {} };</code>

以上がSFINAE がクラス テンプレートのメンバー関数で失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。