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.