Home > Backend Development > C++ > body text

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

Susan Sarandon
Release: 2024-10-25 01:50:30
Original
829 people have browsed it

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

Disambiguating Multiple Inheritance Class Members

Consider the following variadic base class template:

<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"; }
};
Copy after login

The foo() member can only be called with a template parameter matching one of the types in the Types pack. Now, let's define a derived class with non-overlapping base types:

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {};</code>
Copy after login

Calling Derived().foo() should intuitively resolve to the Base base class. However, the compiler complains of ambiguity.

Why the Compiler Cannot Resolve the Ambiguity:

The merge rules for member lookup [class.member.lookup] state that when the derived class has an empty declaration set (no members), the lookup sets from all base classes must be merged. In our case, the base classes have differing declaration sets, so the merge fails.

Solutions:

To avoid this ambiguity, we can add using declarations to the derived 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>
Copy after login

By introducing overloads of foo in the derived class, we effectively bypass the merge rules.

Using a Collector Class:

Alternatively, we can use a template class to aggregate the using declarations from all base classes:

<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>
Copy after login

This approach is more efficient to compile in C 17, as it allows pack expansion of using declarations.

The above is the detailed content of Why Does Multiple Inheritance Ambiguity Occur in C When Calling a Variadic Template Member Function?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!