Ambiguïté dans la levée de l'ambiguïté de l'héritage multiple
Lors du traitement de l'héritage multiple à l'aide de classes de base de modèles, un problème potentiel se pose concernant la résolution ambiguë des fonctions membres. Considérez le scénario suivant :
<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"; } };
Ici, la fonction foo() n'est appelable que lorsque le paramètre de modèle correspond à l'un des types du pack Types. Désormais, si une classe dérivée hérite de plusieurs classes de base avec des ensembles de types qui ne se chevauchent pas, le compilateur peut rencontrer une ambiguïté lors de la résolution de l'appel foo().
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> {};</code>
Dans ce cas, l'appel Derived(). foo
Pourquoi le compilateur ne peut pas résoudre l'ambiguïté
L'erreur de compilation survient en raison des règles de fusion pour la recherche de fonctions membres. Selon le standard C, si la fonction membre n'est pas déclarée dans la classe dérivée elle-même, le processus de recherche recherche à son tour dans les classes de base. Cependant, si les ensembles de déclarations dans les classes de base diffèrent, la fusion devient ambiguë.
Dans le scénario donné, la classe dérivée Derived ne déclare pas explicitement foo(), le compilateur doit donc fusionner les ensembles de recherches du deux classes de base. Étant donné que les classes de base contiennent différents ensembles de déclarations pour foo(), la fusion entraîne une ambiguïté.
Solutions
Pour résoudre cette ambiguïté, une option consiste à utiliser des déclarations using dans la classe dérivée pour importer explicitement les fonctions membres souhaitées. Cependant, cela nécessite que l'utilisateur ajoute ces déclarations, ce qui peut être verbeux et peu pratique pour les grandes listes de types.
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> { using Base<int, char>::foo; using Base<double, void>::foo; };</code>
Alternativement, on peut utiliser une classe d'assistance qui collecte et fusionne les fonctions membres de toutes les classes de base. , permettant à la classe dérivée d'y accéder directement.
<code class="cpp">template <typename... Bases> struct BaseCollector : Bases... { using Bases::foo...; }; struct Derived : BaseCollector<Base<int, char>, Base<double, void>> {};</code>
Avec cette approche, l'utilisateur n'a pas besoin d'ajouter de déclarations supplémentaires pour résoudre l'ambiguïté. La classe BaseCollector fusionne efficacement les ensembles de déclarations de toutes les classes de base, rendant la fonction foo() disponible pour la classe dérivée sans ambiguïté.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!