c++templatesmultiple-inheritancepolymorphic-functions

Template resolution in method with a class template parameter is not working when using multiple inheritance in base class. Why? How?


Consider the following code:


template<typename T>
struct Ambiguous_C {
    void func(T);
};

struct Ambiguous_F {
    template<typename T>
    void func(T);
};

struct Conflicted_F : public Ambiguous_F{
    void test (){
        func(1);
        func<int>(1);
        func(1.1f);
        func<float>(1.1f);
    }
};
struct Conflicted_C : public Ambiguous_C<int>, Ambiguous_C<float>{
    void test (){
        //func(1);                         /* Error */
        Ambiguous_C<int>::func(1);
        //func(1.1f);                      /* Error */
        Ambiguous_C<float>::func(1.1f);
    }
};
Member 'func' found in multiple base classes of different types

This was compiled using clang 20.1.2

I expected the function calls in Conflicted_C::test() to resolve the overloaded function call based on the function signature, just like the code shown in Conflicted_F::test(). Are there additional considerations taken into account with regards to templated classes that I am not aware of?

Is there a way to implement a templated base class/ method, such that the explicit base class Ambiguous_C:: in front of a call to func can be omitted?

I noticed this gives the same error:


void f_func(int);
void f_func(float);

struct Ambiguous_P1 {
    void func(int);
};

struct Ambiguous_P2 {
    void func(float);
};

struct Conflicted_P : public Ambiguous_P1, Ambiguous_P2{
    void test() {
        func(1);             /* Error */
        func(1.1f);          /* Error */

        f_func(1);           /* Works */
        f_func(1.1f);        /* Works */
    }
};

But the question remains the same. Why is the resolution of this ambiguous call not possible based on function signature?


Solution

  • You have to add some using:

    struct Conflicted_C : public Ambiguous_C<int>, Ambiguous_C<float>{
        using Ambiguous_C<int>::func;
        using Ambiguous_C<float>::func;
        void test (){
            func(1);                         /* OK */
            Ambiguous_C<int>::func(1);
            func(1.1f);                      /* OK */
            Ambiguous_C<float>::func(1.1f);
        }
    };
    

    Demo