我在解决以下代码中的问题时遇到问题...
#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模板。
答案 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>
。