So, I was working on an solution on how to solve the problem in Looking for design pattern to reduce virtual method overloads
My idea was too use variadic templates to describe which types may be accepted by a specific class. This might have a small use case, but I like to play around with templates...
Here is what I came up with (so far):
struct Struct
{
virtual void doit() = 0;
};
struct StructA : Struct
{
void doit() { std::cout << "A" << std::endl; }
};
struct StructB : Struct
{
void doit() { std::cout << "B" << std::endl; }
};
struct StructC : Struct
{
void doit() { std::cout << "C" << std::endl; }
};
template <typename Type>
struct Accepter
{
void accept(const Type& t) { t.doit(); };
};
template <typename...Types>
struct MultiAccepter : Accepter<Types>... {};
When passing only a single type to MultiAccepter
everything does as it should.
The problems only occur as soon as I pass 2 or more template parameter types.
It looks like the compiler looses its ability to differ between distinct types.
int main()
{
StructA struct_a;
StructB struct_b;
Accepter<StructA> accept_a;
Accepter<StructB> accept_b;
MultiAccepter<StructA> accept_multi_a;
MultiAccepter<StructB> accept_multi_b;
MultiAccepter<StructA, StructB> accept_multi_ab;
accept_a.accept(struct_a); //OK
accept_b.accept(struct_b); //OK
accept_multi_a.accept(struct_a); //OK
accept_multi_b.accept(struct_b); //OK
accept_multi_ab.accept(struct_a); //NOK:
// error C2385: ambiguous access of 'accept'
// note : could be the 'accept' in base 'Accepter<StructA>'
// note : or could be the 'accept' in base 'Accepter<StructB>'
accept_multi_ab.accept(struct_b); //NOK:
// error C2385: ambiguous access of 'accept'
// note : could be the 'accept' in base 'Accepter<StructA>'
// note : or could be the 'accept' in base 'Accepter<StructB>'
// error C2664 : 'void Accepter<StructA>::accept(const Type &)' : cannot convert argument 1 from 'StructB' to 'const StructA &'
// with
// [
// Type = StructA
// ]
// note : Reason : cannot convert from 'StructB' to 'const StructA'
// note : No user - defined - conversion operator available that can perform this conversion, or the operator cannot be called
return 0;
}
Trying to compile the code with gcc 5.2
doesn't work either:
http://goo.gl/oVLHT8
I guess it's just a simple problem, but I just can't find a solution for it. Does somebody know what I'm doing wrong?
P.S.: The example on this side describes a similar pattern: http://natsys-lab.blogspot.de/2013/07/c-variadic-templates-and-multiple.html
Update: It looks like the base class Accepter<StructB>
defines a function void accept(const StructA&)
. I still don't get why this is the case.