Maison > développement back-end > C++ > le corps du texte

Pourquoi une ambiguïté d'héritage multiple se produit-elle en C lors de l'appel d'une fonction membre de modèle variadique ?

Susan Sarandon
Libérer: 2024-10-25 01:50:30
original
829 Les gens l'ont consulté

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

Désambiguïser plusieurs membres de la classe d'héritage

Considérez le modèle de classe de base variadique 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"; }
};
Copier après la connexion

Le foo() member ne peut être appelé qu'avec un paramètre de modèle correspondant à l'un des types du pack Types. Maintenant, définissons une classe dérivée avec des types de base qui ne se chevauchent pas :

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {};</code>
Copier après la connexion

L'appel de Derived().foo() devrait intuitivement se résoudre en Base classe de base. Cependant, le compilateur se plaint d'ambiguïté.

Pourquoi le compilateur ne peut pas résoudre l'ambiguïté :

Les règles de fusion pour la recherche de membres [class.member.lookup] indiquent que lorsque la classe dérivée a un ensemble de déclarations vide (aucun membre), les ensembles de recherches de toutes les classes de base doivent être fusionnés. Dans notre cas, les classes de base ont des ensembles de déclarations différents, donc la fusion échoue.

Solutions :

Pour éviter cette ambiguïté, nous pouvons ajouter des déclarations using aux classes dérivées 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>
Copier après la connexion

En introduisant des surcharges de foo dans la classe dérivée, nous contournons efficacement les règles de fusion.

Utilisation d'une classe Collector :

Alternativement, nous pouvons utiliser une classe modèle pour regrouper les déclarations using de toutes les classes de base :

<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>
Copier après la connexion

Cette approche est plus efficace à compiler en C 17, car elle permet l'expansion du pack de déclarations using.

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!