C ++可变参数类模板和成员函数

时间:2015-11-03 15:12:05

标签: c++ c++11 variadic-templates void

我在解决以下代码中的问题时遇到问题...

#include <functional>

template<typename... ARGS>
class MyClass {
public :
    void function(ARGS... args)
    {
    }
};

int main(int argc, char * argv[])
{
    MyClass<int>        myClassInt;      // works fine
    MyClass<int, float> myClassIntFloat; // works fine
    MyClass<void>       myClassVoid;     // <---- won't compile

    return 0;
}

如果我在 void 上实例化MyClass,那么Clang非常正确地拒绝编译它,抱怨 MyClass&lt; void&gt; :: function 不是合法的定义。然而,我真正的类需要能够在空白上实例化这种事物。多年来我一直盯着这个,我一直困扰着我需要绕过它的SFINAE jiggery-pokery模板。

1 个答案:

答案 0 :(得分:4)

在使用时使用MyClass<>,或者这个黑客:

template<typename... ARGS>
class MyClass {
public :
  void function(ARGS... args)
  {}
};
template<>
class MyClass<void>:public MyClass<> {
public :
  using MyClass<>::MyClass; // inherit ctors
};

MyClass<void>中,您可能还需要执行其他操作,以充当MyClass<>的相对透明的代理。

我们可以通过不直接使用MyClass来避免这些问题。

template<typename... ARGS>
class MyClass_t {
public :
  void function(ARGS... args)
  {}
};

template<class...Args>
struct MyClass_helper {
  using type=MyClass_t<Args...>;
};
template<>
struct MyClass_helper<void>:MyClass_helper<> {};
template<class...Args>
using MyClass=typename MyClass_helper<Args...>::type;

现在,MyClass<void>扩展为MyClass_t<>MyClass<int, float>扩展为MyClass_t<int,float>

我们不直接使用MyClass_t,而是通过MyClass<...>命名。这种技术的缺点是MyClass<???>如果用作函数参数,则是非推导的上下文;因此,在这些情况下,您必须使用MyClass_t<???>,他们将看不到void

我首选的解决方案是直接使用MyClass<>代替MyClass<void>