decltype,result_of或typeof?

Nei*_*l G 12 c++ type-inference c++11

我有:

class A {
public:
    B           toCPD() const;
Run Code Online (Sandbox Code Playgroud)

和:

template<typename T>
class Ev {
public:
    typedef result_of(T::toCPD()) D;
Run Code Online (Sandbox Code Playgroud)

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

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

既不是类型也不是类型的工作.

Pot*_*ter 34

因为您获得的结果取决于模板参数,所以typedef typename是必要的.

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

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

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

typedef typename decltype( std::declval<T>().toCPD() ) D;
Run Code Online (Sandbox Code Playgroud)

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


typeof是GCC的等效前C++ 11扩展decltype,它也被克隆到其他编译器中.以下是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;
Run Code Online (Sandbox Code Playgroud)

但是,这非常脆弱,因为&T::toCPD如果存在任何重载,则无法解析,例如非const版本.尽管这是真的T *还是T const *必须明确地写出来!在大多数情况下,你最好还是decltypedeclval.