I am trying to create class deriving from variadic template. Here is the code:
struct Some { };
template < class Base, class T >
struct Feature
{
protected:
void DoStuff(T& t) { }
};
template < class T, class ... Ts >
struct MultiFeature
: public Feature< T, Ts >...
{
};
class TestFeature
: public MultiFeature< Some, std::int16_t, std::string >
{
public:
void TestDoStuff()
{
std::int16_t i;
DoStuff(i);
}
};
Feature should be a simple wrapper around some basic type (in this case, integer and string), providing some functionality to class deriving from it. MultiFeature is used so that I do not have to derive from Feature< std::int16_t >
, Feature< std::string >
.
As far as I understand, there should be no ambiguity in this case, because there are two different DoStuff
functions, each taking different parameter type, however VS2017 complains about ambiguous access. Is this correct behavior? If so, is there any simple workaround around this problem?
EDIT
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using
(Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using (Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
If you can use C++17, it's trivially simple
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
Unfortunately the variadic using
is introduced in C++17 so, in C++11 and C++14, the best I can imagine is a MultiFeature
recursive definition
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
The following is a full compiling example (with both cases)
struct Some { };
template <typename, typename T>
struct Feature
{
protected:
void DoStuff (T &) { }
};
#if 0
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
#else
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
#endif
struct TestFeature
: public MultiFeature<Some, short, int, long, long long>
{
void TestDoStuff ()
{ int a{}; DoStuff(a); }
};
int main ()
{
TestFeature tf;
}