我在以下代码中遇到问题时遇到问题...
#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无效,则Clang非常正确地拒绝编译此代码,抱怨 MyClass ::function 不是合法定义。但是,我拥有的真实类需要能够在void上实例化此类内容。我一直盯着这个看了很长时间,对于我需要解决的SFINAE jiggery-pokery模板我一无所知。
最佳答案
请在使用时使用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>
。