【发布时间】:2014-06-01 08:31:51
【问题描述】:
使用 SFINAE,可以访问可变参数类模板的各个元素。当基类从可变参数类模板继承,然后派生类从基类和可变参数类模板(使用不同的模板参数)继承时,就会出现我的问题。关于应该遵循哪个继承链存在歧义。有没有办法解决歧义?
例如:
// compile with flag: -std=c++11
#include <type_traits>
struct A { int x; };
struct B { int x; };
struct C { int x; };
struct D { int x; };
template <class ... Params> class Parameter { };
template <class Param, class ... Tail>
class Parameter<Param, Tail ...> : public Param, public Parameter<Tail ...>
{
public:
//! Get a parameter
template <class Param2>
typename std::enable_if<std::is_same<Param, Param2>::value, int>::type
getParam() const
{ return Param::x; }
//! Get a parameter. Delegate false template matches down the Tail... inheritance line (see SFINAE)
template <class Param2>
typename std::enable_if<! std::is_same<Param, Param2>::value, int>::type
getParam() const
{ return Parameter<Tail ...>::template getParam<Param2>(); }
};
class Base : public Parameter<A, B>
{ };
class Derived : public Base, public Parameter<C, D>
{ };
int main(int const argc, char const * argv[])
{
Base base;
int a = base.getParam<A>(); // ok
int b = base.getParam<B>(); // ok
Derived derived;
int c0 = derived.getParam<C>(); // error: request for member ‘getParam’ is ambiguous
int c1 = derived.Derived::getParam<C>(); // error: request for member ‘getParam’ is ambiguous
int c2 = derived.Parameter<C, D>::getParam<C>(); // ok but syntax overly complex, especially if many params
int a0 = derived.getParam<A>(); // error: request for member ‘getParam’ is ambiguous
int a1 = derived.Base::getParam<A>(); // ok, could be acceptable if also worked on Derived
int a2 = derived.Parameter<A, B>::getParam<A>(); // ok but syntax overly complex and confusing
return 0;
}
我意识到几个主要的设计更改可以解决这个问题:1)摆脱可变参数类模板,而是从每个参数一次派生一个 2)使参数成为成员变量。但我的问题是我是否可以保留可变参数类模板同时避免歧义。
【问题讨论】:
-
就个人而言,我会这样写:ideone.com/BbLKxb
-
@Jarod42 这不是评论,这是我认为的答案!
-
@jarod42 在单继承情况下的轻微行为变化:如果我们是
Parameter<int,int>,上面得到第一个int,而您的代码是模棱两可的。如果 OP 关心,可以修补,但 OP 可能希望在这种情况下出现错误.... -
所有给定参数的类型在我们的应用程序中都是不同的,所以没有问题,但请参阅下面的其他评论。
-
附加说明:理想情况下,我希望 a0 和 c0 之类的东西可以工作,如果没有,类似于 a1 和 c1 的东西就可以了。像 a2 和 c2 这样的东西太麻烦了,会让我完全远离可变参数模板实现。因此,不必通过原始帖子中提到的所有错误情况,只需避免重新列出所有参数参数就足够了。
标签: templates inheritance c++11 variadic-templates sfinae