2

I have faced some code snippets that a class can inherited from another class via its template parameter. However, I do not understanding why I need to have the three using line in struct D. I try to call the say_hi() function of d but it states error: request for member ‘say_hi’ is ambiguous and the error gone if I have the three using lines. Can anyone tell me why?

struct C1 {
  void say_hi(int) { puts("int hi"); }
};
struct C2 {
  void say_hi(char) { puts("char hi"); }
};
struct C3 {
  void say_hi(double) { puts("double hi"); }
};
template<typename T, typename U, typename V>
struct D : T, U, V { 
  using T::say_hi;
  using U::say_hi;
  using V::say_hi;
};
D<C1, C2, C3> d;
  • You can manually specify without the `using`s which one to use BTW: `d.C1::say_hi(1)` will call `say_hi(int)`. I'm not sure how the `using`s clear the ambiguity that was there, but this might be related to the that. – mediocrevegetable1 Aug 15 '21 at 08:54
  • 1
    Doing `using T::say_hi;`, `using U::say_hi;` and `using V::say_hi;` brings the overloads of `say_hi` from `C1`, `C2` and `C3` into `D`. Without them, the compiler isn't able to figure out whether you are referring to `d.C1::say_hi`, `d.C2::say_hi` or `d.C3::say_hi`. – Ruks Aug 15 '21 at 08:59

1 Answers1

3

This is a variation on how the hiding rule works in c++ : https://isocpp.org/wiki/faq/strange-inheritance#hiding-rule . But you actually dont declare any method in D which could overload the base class methods. C++ compiler does not search for all possible overloads of your function call in whole inheritance tree but stop when it finds a correct overload (adhering to standard). To modify this base working of compiler, you can add using declarations to specify which overloads should be visible or to resolve ambiguities.

marcinj
  • 48,511
  • 9
  • 79
  • 100