2010-07-24 55 views
2

使用SFINAE对于一些复杂的原因,追赶函子,我想任何支持T型(从模板来)转换成的我选择类型的列表。为此,我尝试使用名为“Convert”的模板结构。例如:结构偏特

Convert<short>::type should be int 
Convert<int>::type should be int 
Convert<char>::type should be int 
Convert<float>::type should be double 
Convert<double>::type should be double 
Convert<const char*>::type should be std::string 
Convert<std::string>::type should be std::string 
etc. 

上面的内容很容易使用模板专门化来实现。但有一种情况是导致问题:

Convert<T>::type where T is a functor should be T 

为了解决这个问题,我想我必须使用SFINAE但我不能设法让它编译。

下面的代码给了我“partial specialization cannot match argument list for primary template”(即写“转换”禁止):

template<typename T, typename = decltype(&T::operator())> 
struct Convert<T>  { typedef T type; }; 

而这一次给了我“template parameter not used or deducible in partial specialization”(即它认为,不使用T):

template<typename T> 
struct Convert<typename std::enable_if<std::is_function<typename T::operator()>::value,T>::type> 
{ typedef T type; }; 

我不知道该怎么做,我所有的尝试都会导致上述两个错误之一。

编辑:我想搭上使用同一模式的其他普通的事情,所以我不能只写“的typedef T形”的非专业结构。

感谢

+0

你是什么意思“抓其他通用的东西”? – GManNickG 2010-07-24 09:34:54

+0

你需要澄清你的意思是“一个仿函数”。功能还不错?或者它只是功能对象?如果是这样,那么用operator()'超载的任何东西?或从'std :: function_object'派生?特定数量的参数? – sbi 2010-07-24 09:42:09

+0

实例:“转换 ::类型是int如果T是可转换为int”,或“转换 ::类型是...如果T具有开始和结束功能”等 – Tomaka17 2010-07-24 09:44:58

回答

2

我建议你使用第一种方法,但要使其工作,你就必须

有一个未使用的模板参数声明主模板:

template <class T, class = void> Convert; 

void参数添加到您现在使用的模板的所有特化。

定义你的“仿函数专业化”是这样的:

template<typename T, typename std::enable_if<std::is_function<typename T::operator()>::value,void>::type> 

这意味着你做的第二个参数void,如果它是一个仿函数(所以它的默认模板参数匹配)或不存在的,如果它不是。

BTW你为什么要使用typename T::operator()typename? AFAIK,operator()不是一种类型。

+0

好主意,谢谢。显然,我甚至不需要在我的其他专业上添加“void”。然而,编译器暂时使用非特殊化的结构,我会尽力使其工作。 – Tomaka17 2010-07-24 10:49:45

+0

你可能是正确的typename,无论如何我尝试了几个东西,如'std :: enable_if <!std :: is_void :: value> :: type',我认为是正确 – Tomaka17 2010-07-24 10:51:39

+0

'Convert :: type>'正在工作,所以在我的情况下肯定有问题 – Tomaka17 2010-07-24 11:05:25