0

When inheriting from a class template multiple times, there is the problem that multiple inheritance of these template classes makes member functions ambiguous (also here), because apparently it is defined that way in the standard.

Question: Why is this defined ambiguous?

Example:

#include <iostream>

template <typename T>
class Base
{
    T val;

public:
    Base(T val) : val(val) {}

    void print(T v)
    {
        std::cout << val << " " << v << std::endl;
    }
};

class Child : public Base<int>, public Base<std::string>
{
public:
    Child() : Base<int>(0), Base<std::string>("0"){}

    // Necessary for successful compilation
//     using Base<int>::print;
//     using Base<std::string>::print;

};

int main()
{
    Child c;

    c.print(1);
    c.print(std::string("1"));
    
    return 0;
}

produces

error: request for member ‘print’ is ambiguous
   38 |     c.print(1);
      |       ^~~~~
   39 |     c.print(std::string("1"));
      |       ^~~~~
note: candidates are: ‘void Base<T>::print(T) [with T = std::__cxx11::basic_string<char>]’
note:                 ‘void Base<T>::print(T) [with T = int]’

Instead of manually spelling out, as suggested here and here,

using Base<int>::print;
using Base<std::string>::print;

I can just create a template:

template<typename T>
void print(T v)
{
    this->Base<T>::print(v);
}

I understand that with this template I tell the compiler in which base class to look, but I fail to understand why that would be necessary in the first place.

vohir
  • 21
  • 4
  • 1
    Doesn't the top answer from [here](https://stackoverflow.com/questions/35874029/ambiguous-multiple-inheritance-of-template-classes) tell you why? – NathanOliver Jan 12 '23 at 15:43
  • 1
    Overloading only applies to names that are defined in the same scope. Those two versions of `print` are defined in two different scopes: `Base` and `Base`, so they do not overload. Pulling them into `Child` with those `using` directives fixes the problem. – Pete Becker Jan 12 '23 at 15:46
  • @NathanOliver No, because this answer does not explain why it is ambiguous. Obviously the function name can be found in both base classes, but the function parameters are different. So I would assume that standard rules for resolving function overloading should make them unambiguous. – vohir Jan 12 '23 at 15:53
  • 1
    Name lookup only looks up the name, and the name is the same even if the signature is different. – NathanOliver Jan 12 '23 at 15:54
  • 2
    BTW, you might simplify the problem with regular (non-template) bases. [Demo](https://godbolt.org/z/EdjezKPYx) – Jarod42 Jan 12 '23 at 16:08

0 Answers0