decltype,result_of或typeof?

时间:2010-05-04 08:28:53

标签: c++ c++11 type-inference

我有:

class A {
public:
    B           toCPD() const;

template<typename T>
class Ev {
public:
    typedef result_of(T::toCPD()) D;

在实例化Ev<A>之后,编译器说:

meta.h:12:错误:'T :: toCPD'不是类型

既不是类型也不是类型。

2 个答案:

答案 0 :(得分:32)

由于您获得的结果取决于模板参数,因此typedef typename是必需的。

decltype是标准的C ++ 11功能。它是一个“运算符”,它接受一个表达式并返回一个类型。

typedef typename decltype( T().toCPD() ) D; // can't use T:: as it's nonstatic

如果T()不是有效的(T不是默认构造的),那么你需要declval这是一个接受类型的函数,并返回一个无意义的,无效的值类型。 declval只能在未评估的上下文中使用,例如decltype

typedef typename decltype( std::declval<T>().toCPD() ) D;

在C ++ 11之前,decltype是Microsoft的MSVC编译器的非标准扩展。它的行为可能会因标准化而略有改变。


typeof是GCC的等效的前C ++ 11扩展,如decltype,它也被克隆到其他编译器中。 Here是GCC的文件。该页面未对功能进行比较,但它指出在使用标准模式typeof时必须调用__typeof__ -std=c++YY,您应该始终执行此操作),它可以在C和C ++中使用。

为了C兼容性,__typeof__将不会从glvalue表达式中解析引用类型。因此,它实际上只适用于C.这可能解释了为什么C ++特性没有继承更加不言自明的名称:GNU不愿意牺牲后向兼容性,而微软不太关心C而且可能需要更少的更改。


result_of是一个C ++ 11元函数(以前在2006年的ISO TR1库中标准化)。它是一个采用可调用类型的模板(例如函数int(void),函数指针int(*)(void),实现operator()的函数类或指向成员函数的指针&T::toCPD )和该类型的参数类型列表,如果调用可行,则提供返回类型。

要将result_of与指向成员函数的指针一起使用,必须在参数列表中包含父对象类型作为this的代理。

typedef typename std::result_of< decltype( & T::toCPD ) ( T * ) >::type D;

这非常脆弱,因为如果存在任何重载,&T::toCPD无法解析,例如非const版本。尽管必须明确写出T *T const *,但事实确实如此!在大多数情况下,您最好使用decltypedeclval

答案 1 :(得分:3)

result_of既不是运算符也不是函数。 result_of是一个元函数,具有模板参数的功能,并在成员类型上设置结果类型

typedef typename result_of<T::toCPD()>::type D;