avoiding ambiguous SFINAE access when both base and derived class have variadic inheritance chains
c++11, inheritance, sfinae, templates, variadic-templates
Solution
I would remove the `getParam` that doesn't match to avoid ambiguity as follow: Demo
template <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;
};
Problem
Using SFINAE, one can access individual elements of a variadic class template. My problem occurs when a base class inherits from a variadic class template, and then a derived class inherits from the base and from the variadic class template again (with different template arguments). An ambiguity exists as to which inheritance chain should be followed. Is there a way to resolve the ambiguity? For example: ``` // 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; } ``` I realize that several major design changes could address the problem: 1) get rid of the variadic Parameter class template, instead derive from each parameter one at a time 2) make the parameters member variables. But my question is whether I could retain the variadic Parameter class template yet avoid the ambiguity.