Search code examples
c++visual-studio-2010templatesmultiple-inheritancename-lookup

Template Member Function Overloading and Multiple Inheritance in C++


I am observing behavior in the below code which I cannot readily explain and would like to understand the theory of better. I cannot seem to find an online documentation source or existing question which covers this particular situation. For reference, I am using Visual Studio C++ 2010 to compile and run the following code:

#include <iostream>
using namespace std;

struct Bottom_Class
{
    template<typename This_Type>
    void Dispatch()
    {
        // A: When this comment is removed, the program does not compile
        //    citing an ambiguous call to Print_Hello
        // ((This_Type*)this)->Print_Hello();

        // B: When this comment is removed instead, the program compiles and
        //    generates the following output:
        //    >> "Goodbye from Top Class!"
        // ((This_Type*)this)->Print_Goodbye<void>();
    }

    void Print_Hello() {cout << "Hello from Bottom Class!" << endl;}

    template<typename This_Type>
    void Print_Goodbye() {cout << "Goodbye from Bottom Class!" << endl;}
};

struct Top_Class
{
    void Print_Hello() {cout << "Hello from Top Class!" << endl;}

    template<typename This_Type>
    void Print_Goodbye() {cout << "Goodbye from Top Class!" << endl;}
};

template<typename Top_Type,typename Bottom_Type>
struct Merged_Class : public Top_Type, public Bottom_Type {};

typedef Merged_Class<Top_Class,Bottom_Class> My_Merged_Class;

void main()
{
    My_Merged_Class my_merged_object;

    my_merged_object.Dispatch<My_Merged_Class>();
}

Why does this work differently for the templated member function vs. non-templated member function cases ?

How does the compiler decide (in the templated case) that Top_Class::Print_Goodbye() is the appropriate overload rather than Bottom_Class::Print_Goodbye() ?

Thank you in advance for your consideration.


Solution

  • In the Dispatch method, This_Type is the same as My_Merged_Class. The My_Merged_Class has two methods with the names of Print_Hello, of course the compiler is going to have problems to distinguish between them.

    The call to Print_Hello in Dispatch, after template replacement, looks like this:

    ((My_Merged_Class*)this)->Print_Hello();
    

    I hope the above substitution helps you see better why there is an ambiguity. The same problem should actually occur for Print_Goodbye, but it might be a bug in the compiler you are using that lets it through.