Home  >  Article  >  Backend Development  >  ## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?

## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?

Barbara Streisand
Barbara StreisandOriginal
2024-10-25 04:58:02530browse

## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?

Ambiguity in Disambiguating Multiple Inheritance

When dealing with multiple inheritance using template base classes, a potential issue arises regarding ambiguous member function resolution. Consider the following scenario:

<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";
  }
};

Here, the function foo() is only callable when the template parameter matches one of the types in the Types pack. Now, if a derived class inherits from multiple base classes with non-overlapping type sets, the compiler may encounter ambiguity when resolving the foo() call.

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

In this case, the call Derived().foo() would ideally call the foo() member function from Base. However, both GCC and Clang report an ambiguity.

Why the Compiler Cannot Resolve the Ambiguity

The compilation error arises because of the merge rules for member function lookup. According to the C standard, if the member function is not declared in the derived class itself, the lookup process searches the base classes in turn. However, if the declaration sets in the base classes differ, the merge becomes ambiguous.

In the given scenario, the derived class Derived does not declare foo() explicitly, so the compiler must merge the lookup sets from the two base classes. Since the base classes contain different declaration sets for foo(), the merge results in ambiguity.

Solutions

To resolve this ambiguity, one option is to use using declarations in the derived class to explicitly import the desired member functions. However, this requires the user to add these declarations, which can be verbose and impractical for large type lists.

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

Alternatively, one can use a helper class that collects and merges the member functions from all base classes, allowing the derived class to access them directly.

<code class="cpp">template <typename... Bases>
struct BaseCollector : Bases...
{
  using Bases::foo...;
};

struct Derived : BaseCollector<Base<int, char>, Base<double, void>>
{};</code>

With this approach, the user does not need to add any additional declarations to resolve the ambiguity. The BaseCollector class effectively merges the declaration sets from all base classes, making the foo() function available to the derived class without ambiguity.

The above is the detailed content of ## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
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