多重継承のあいまいさの解消
テンプレート基本クラスを使用して多重継承を処理する場合、あいまいなメンバー関数の解決に関して潜在的な問題が発生します。次のシナリオを考えてみましょう:
template
class Base {
public:
template
typename std::enable_if::value>::type foo() {
std::cout ここで、関数 foo() は、テンプレート パラメーターが Types パック内のいずれかの型と一致する場合にのみ呼び出し可能です。現在、派生クラスが型セットが重複していない複数の基本クラスから継承している場合、コンパイラーは foo() 呼び出しを解決するときにあいまいさが発生する可能性があります。
struct Derived: public Base,
public Base
{};
この場合、Derived().foo() の呼び出しは、理想的には Base から foo() メンバー関数を呼び出します。ただし、GCC と Clang は両方ともあいまいさを報告します。
コンパイラーがあいまいさを解決できない理由
メンバー関数検索のマージ ルールが原因でコンパイル エラーが発生します。 C 標準によれば、メンバー関数が派生クラス自体で宣言されていない場合、検索プロセスでは基本クラスが順番に検索されます。ただし、基底クラスの宣言セットが異なる場合、マージは曖昧になります。
指定されたシナリオでは、派生クラス Derived は foo() を明示的に宣言していないため、コンパイラーは、基底クラスからのルックアップ セットをマージする必要があります。 2 つの基本クラス。基本クラスには foo() の異なる宣言セットが含まれているため、マージの結果があいまいになります。
Solutions
このあいまいさを解決するには、using 宣言を使用するオプションがあります。派生クラスで必要なメンバー関数を明示的にインポートします。ただし、これにはユーザーがこれらの宣言を追加する必要があり、冗長になる可能性があり、大規模な型リストの場合は実用的ではありません。
struct Derived: public Base,
public Base
{
using Base::foo;
using Base::foo;
};
あるいは、すべての基本クラスからメンバー関数を収集およびマージするヘルパー クラスを使用して、派生クラスがそれらの関数に直接アクセスできるようにすることもできます。
template
struct BaseCollector : Bases...
{
using Bases::foo...;
};
struct Derived : BaseCollector , Base>
{};
このアプローチでは、ユーザーは曖昧さを解決するために追加の宣言を追加する必要はありません。 BaseCollector クラスは、すべての基本クラスからの宣言セットを効果的にマージし、派生クラスで曖昧さなく foo() 関数を使用できるようにします。
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3