使用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)使参数成员变量.但我的问题是我是否可以保留可变参数类模板,但避免歧义.
我会删除不匹配的getParam以避免歧义,如下所示: Demotemplate <class ... Params> class Parameter; template <class Param> class Parameter<Param> : public Param { public: //! Get a parameter template <class Param2> typename std::enable_if<std::is_same<Param, Param2>::value, int>::type getParam() const { return Param::x; } }; template <class Param, class ... Tail> class Parameter<Param, Tail ...> : public Parameter<Param>, Parameter<Tail...> { public: using Parameter<Param>::getParam; using Parameter<Tail...>::getParam; }; class Base : public Parameter<A, B> {}; class Derived : public Base, public Parameter<C, D> { public: using Base::getParam; using Parameter<C, D>::getParam; };