Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance Template Class

class messageA {
};

class messageB {
};

template<class T>
class queue {
public:
    virtual ~queue() {}
    void submit(T& x) {}
};

class A : public queue<messageA>, public queue<messageB>
{
};

int main()
{
    A aa;
    aa.submit(messageA());
    aa.submit(messageB());
}

My first thought is, the above code should be fine, as class A will contains 2 overloaded submit functions, which will accept messageA and messageB object.

However, the compiler gives me the following error :

May I know why there is an ambiguous? Isn't it is quite obvious that, for the 1st submit call, I want to call messageA version? For the 2nd submit call, I want to call messageB version?


------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
        with
        [
            T=messageA
        ]
.\main.cpp(22) : error C3861: 'submit': identifier not found
like image 239
Cheok Yan Cheng Avatar asked Jul 29 '10 09:07

Cheok Yan Cheng


2 Answers

I have no compiler right now, but I guess one inheritance could hide the other : The compiler will use Koenig Lookup to find the right symbol, and if I remember correctly, once the compiler find a suitable symbol (i.e., a method called "submit"), it will stop searching for others in parent and/or outer scopes.

In this case, I thought both inheriting classes would be searched for the symbol, but without your exact compiler (Visual C++ 2003 ? 2008 ? 2010 ?), I cannot guess much more.

After some thoughts, another possibility is that the compiler did find both symbols, but is unable to decide which to call (at that moment of symbol resolution, the compiler cares only for symbol name, not its exact prototype). I believe this last explanation to be the right one.

Try adding using statements in your derived classes :

class A : public queue<messageA>, public queue<messageB>
{
   using queue<messageA>::submit ;
   using queue<messageB>::submit ;
} ;

to bring both the submit methods directly in the A class scope.

Note, too, that your submit methods are taking messages as non-const reference, while in the constructor, your message parameters are temporaries (and thus, const r-values).

Re-writting the main as:

int main()
{
    A aa;
    messageA mA ;
    messageA mB ;
    aa.submit(mA);
    aa.submit(mB);
}

could help compile (this could explain the compiler error on line 22).

Or you could change the prototype of your submit methods to accept const references instead of non-const references.

Note: Still without compiler, so trying to brain-debug your code... :-P ...

like image 60
paercebal Avatar answered Sep 22 '22 21:09

paercebal


Something* smth1 = ((Base<Something> *)d)->createBase<Something>();

The above code works fine.

like image 38
santhosh Avatar answered Sep 24 '22 21:09

santhosh