複数の継承クラス メンバーの曖昧さの解消
次の可変個引数基本クラス テンプレートを考えてみましょう。
<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
コンパイラがあいまいさを解決できない理由:
メンバー検索 [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 サイトの他の関連記事を参照してください。