我有:
class A {
public:
B toCPD() const;
和
template<typename T>
class Ev {
public:
typedef result_of(T::toCPD()) D;
在实例化Ev<A>
之后,编译器说:
既不是类型也不是类型。
答案 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 *
,但事实确实如此!在大多数情况下,您最好使用decltype
和declval
。
答案 1 :(得分:3)
result_of既不是运算符也不是函数。 result_of是一个元函数,具有模板参数的功能,并在成员类型上设置结果类型
typedef typename result_of<T::toCPD()>::type D;