从可变参数模板继承时访问基类函数时的模棱两可的访问错误

时间:2019-06-06 18:19:15

标签: c++11 templates variadic-templates

我正在尝试创建从可变参数模板派生的类。这是代码:

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);
    }
};

功能应该是一些基本类型(在这种情况下为整数和字符串)的简单包装,为从其派生的类提供一些功能。使用MultiFeature使得我不必从Feature< std::int16_t >Feature< std::string >派生。

据我了解,在这种情况下应该没有歧义,因为有两个不同的DoStuff函数,每个函数采用不同的参数类型,但是VS2017抱怨访问不明确。这是正确的行为吗?如果是这样,是否有解决此问题的简单方法?

编辑

似乎编译器就在这里,但是在此答案中,建议的解决方法是将usingAmbiguous access to base class template member function)引入基类成员函数。是否可以对可变参数模板基类执行此操作?

1 个答案:

答案 0 :(得分:0)

  

似乎编译器就在这里,但是在此答案中,建议的解决方法是通过使用将基类成员函数带入范围(对基类模板成员函数的歧义访问)。是否可以对可变参数模板基类执行此操作?

如果您可以使用C ++ 17,这很简单

template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
 {
   using Feature<T, Ts>::DoStuff...;
 };

不幸的是,可变参数using是在C ++ 17中引入的,因此,在C ++ 11和C ++ 14中,我能想到的最好的是MultiFeature递归定义

// 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;
 };

以下是完整的编译示例(两种情况)

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;
 }