declval<T>()是否仅是(*(T*)NULL)的老把戏的替代品,而无需再担心T的构造函数,从而获得decltype中的T实例?

这是一些示例代码:

struct A {};

struct B {
    A a;
};

typedef decltype((*(B*)nullptr).a) T1;
typedef decltype(declval<B>().a) T2;

cout << "is_same: " << is_same<T1, T2>::value << endl;

因为T1和T2是同一类型,所以会打印1。

如果declval不仅仅是一个替代品,有什么区别,它在哪里有用?

最佳答案

declval()的优点是,如果在评估的上下文中使用它(即odr-used),则程序格式错误(20.2.4p2),并且需要发出诊断信息(根据1.4p1)。通常,这是通过库中的static_assert强制执行的:

c++/4.7/type_traits: In instantiation of '[...] std::declval() [...]':
source.cpp:3:22:   required from here
c++/4.7/type_traits:1776:7: error: static assertion failed: declval() must not be used!
declval也适用于引用类型:
using S = int &;
using T = decltype(std::declval<S>());
using U = decltype(*(S *)nullptr);  // fails

如果类型不是引用类型,则declval将给出右值类型,而nullptr将给出左值。

08-16 02:09