多重継承のあいまいさの解消
テンプレート基本クラスを使用して多重継承を扱う場合、あいまいなメンバー関数の解決に関して潜在的な問題が発生します。次のシナリオを考えてみましょう:
<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() は、テンプレート パラメーターが Types パック内のいずれかの型と一致する場合にのみ呼び出し可能です。ここで、派生クラスが型セットが重複していない複数の基本クラスから継承している場合、コンパイラーは foo() 呼び出しを解決するときにあいまいさに遭遇する可能性があります。
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> {};</code>
この場合、呼び出しは Derived() です。 foo
コンパイラーがあいまいさを解決できない理由
コンパイル エラーは、メンバー関数検索のマージ ルールが原因で発生します。 C 標準によれば、メンバー関数が派生クラス自体で宣言されていない場合、検索プロセスでは基本クラスが順番に検索されます。ただし、基底クラスの宣言セットが異なる場合、マージは曖昧になります。
指定されたシナリオでは、派生クラス Derived は foo() を明示的に宣言していないため、コンパイラーは、基底クラスからのルックアップ セットをマージする必要があります。 2 つの基本クラス。基本クラスには foo() の異なる宣言セットが含まれているため、マージの結果があいまいになります。
解決策
このあいまいさを解決するには、using 宣言を使用することが 1 つのオプションです。派生クラスで必要なメンバー関数を明示的にインポートします。ただし、これにはユーザーがこれらの宣言を追加する必要があり、大規模な型リストでは冗長で非現実的になる可能性があります。
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> { using Base<int, char>::foo; using Base<double, void>::foo; };</code>
代わりに、すべての基本クラスからメンバー関数を収集してマージするヘルパー クラスを使用することもできます。
<code class="cpp">template <typename... Bases> struct BaseCollector : Bases... { using Bases::foo...; }; struct Derived : BaseCollector<Base<int, char>, Base<double, void>> {};</code>
このアプローチでは、ユーザーは曖昧さを解決するために追加の宣言を追加する必要はありません。 BaseCollector クラスは、すべての基本クラスの宣言セットを効果的にマージし、派生クラスで曖昧さなく foo() 関数を使用できるようにします。
以上が## テンプレート基本クラスでの多重継承によりメンバー関数の解決があいまいになるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。