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;它打印1,因为T1和T2是同一类型。
如果declval不仅仅是一个替代品,那么它有什么区别,它在哪里有用?
发布于 2013-02-02 08:06:31
declval()的优点是,如果在评估的上下文中使用它(即,使用odr),则程序是病态的(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会给出一个左值。
发布于 2013-02-02 20:45:30
不,declval<T>()和(*(T*)nullptr)不一样。而且decltype(expr.bar)和decltype((expr.bar))是不一样的。
前一个比较比较表达式。后一次使用decltype检查表达式,前一次使用decltype检查expr.bar的声明类型。因此,您必须对decltype操作数的用法进行整理,以便对这些类型进行有用的比较,您会发现它们是不同的。
struct A {};
struct B {
A a;
};
// E1: B().a
// E2: declval<A>().a
// E3: (*(B*)0).a
// E4: ((B&&)(*(B*)0)).a在这4个表达式中,所有表达式都具有A类型。E1是一个prvalue (在C++14中它是一个X值。一些编译器可能会将其视为x值,即使在C++11模式下也是如此),E2就是x值。E3是一个左值,而E4又是一个x值。
// T1: decltype((*(B*)0).a)
// T2: decltype(((*(B*)0).a))在这两种类型中,第一个decltype给出了由表达式命名的成员的类型。该成员的类型为A,因此T1为A。第二个decltype生成表达式的类型,如果表达式是左值,则由&修改;如果表达式是x值,则由&&修改。表达式是一个左值,所以T2是A&。
https://stackoverflow.com/questions/14657092
复制相似问题