2015-11-03 91 views
1

我在周围工作的问题在下面的代码中的问题... C++可变参数类模板和成员函数

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

锵相当正确地拒绝编译这个,如果我实例化无效 MyClass的,抱怨MyClass <void> :: function不是一个合法的定义。然而,我所需要的真正的类需要能够在void上实例化这种类型的东西。我一直在盯着这个很长一段时间,我坚持什么模板SFINAE jiggery-pokery我需要解决它。

+0

我意识到我需要以某种方式专注于** void **的情况,但是我无法看到一种不会被一般可变参数情况所捕获的方法。 – brunobignose

+1

因为使用'void'相当于声明了无效的成员函数'void MyClass :: function(void args)'。专业化的确是解决你的问题的关键。 –

+0

为什么不能'MyClass <>'? – Yakk

回答

4

要么使用MyClass<>在使用点,或本hack:

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>

+0

感谢您的答案!我不知道如何将它实例化为MyClass <>,这看起来完美无缺。 – brunobignose

相关问题