【发布时间】:2015-11-09 17:54:48
【问题描述】:
所以,我正在研究如何解决Looking for design pattern to reduce virtual method overloads中的问题的解决方案
我的想法是使用可变参数模板来描述特定类可以接受哪些类型。这可能有一个小用例,但我喜欢玩模板...
这是我想出的(到目前为止):
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>... {};
当只将一个类型传递给MultiAccepter 时,一切都会按其应有的方式进行。
只有当我传递 2 个或更多模板参数类型时,才会出现问题。
看起来编译器失去了区分不同类型的能力。
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;
}
尝试使用gcc 5.2 编译代码也不起作用:
http://goo.gl/oVLHT8
我想这只是一个简单的问题,但我就是找不到解决方案。 有人知道我做错了什么吗?
P.S.: 这边的例子描述了一个类似的模式: http://natsys-lab.blogspot.de/2013/07/c-variadic-templates-and-multiple.html
更新:看起来基类Accepter<StructB>定义了一个函数void accept(const StructA&)。我还是不明白为什么会这样。
【问题讨论】:
-
这是骗人的……某事。如果没有 using 声明,来自不同基类范围的名称不会重载。
-
@T.C.正确的。它需要一个可变参数 using 指令,我不知道该怎么做。另请注意stackoverflow.com/questions/7870498/…
-
@T.C. This?甚至有相同的评论来自你
标签: c++ templates inheritance c++14 multiple-inheritance