ホームページ >バックエンド開発 >C++ >C で可変引数テンプレートのメンバー関数を呼び出すときに多重継承のあいまいさが発生するのはなぜですか?

C で可変引数テンプレートのメンバー関数を呼び出すときに多重継承のあいまいさが発生するのはなぜですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-25 01:50:30933ブラウズ

Why Does Multiple Inheritance Ambiguity Occur in C   When Calling a Variadic Template Member Function?

複数の継承クラス メンバーの曖昧さの解消

次の可変個引数基本クラス テンプレートを考えてみましょう。

<code class="cpp">template <typename... Types>
class Base {
public:
    template <typename T>
    typename std::enable_if<Contains<T, Types...>::value>::type
    foo() { std::cout << "Base::foo()\n"; }
};

foo() member は、Types パック内のいずれかの型と一致するテンプレート パラメーターを使用してのみ呼び出すことができます。ここで、重複しない基本型を使用して派生クラスを定義しましょう。

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {};</code>

Calling Derived().foo() は、直感的に Base に解決されるはずです。基本クラス。ただし、コンパイラはあいまいさを報告します。

コンパイラがあいまいさを解決できない理由:

メンバー検索 [class.member.lookup] のマージ ルールには、次のことが記載されています。派生クラスに空の宣言セット (メンバーなし) がある場合、すべての基本クラスからの検索セットをマージする必要があります。この場合、基本クラスの宣言セットが異なるため、マージは失敗します。

解決策:

この曖昧さを回避するには、派生クラスに using 宣言を追加します。 class:

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {
    using Base<int, char>::foo;
    using Base<double, void>::foo;
};</code>

派生クラスに foo のオーバーロードを導入することで、マージ ルールを効果的にバイパスします。

コレクター クラスの使用:

あるいは、テンプレート クラスを使用して、すべての基本クラスからの using 宣言を集約することもできます。

<code class="cpp">template <typename... Bases>
struct BaseCollector;

template <typename Base, typename... Bases>
struct BaseCollector<Base, Bases...> : Base, BaseCollector<Bases...> {
    using Base::foo;
    using BaseCollector<Bases...>::foo;
};

struct Derived : BaseCollector<Base2<int>, Base2<std::string>> {};</code>

このアプローチは、using 宣言のパック拡張が可能であるため、C 17 でコンパイルする方が効率的です。

以上がC で可変引数テンプレートのメンバー関数を呼び出すときに多重継承のあいまいさが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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