首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >declval<T>()是否与(*(T*)nullptr)相同?

declval<T>()是否与(*(T*)nullptr)相同?
EN

Stack Overflow用户
提问于 2013-02-02 08:01:11
回答 2查看 3.1K关注 0票数 25

declval<T>()仅仅是(*(T*)NULL)的老把戏的替代品吗?不用担心T的构造函数,就可以在decltype中获得T的实例。

下面是一些示例代码:

代码语言:javascript
复制
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不仅仅是一个替代品,那么它有什么区别,它在哪里有用?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-02 08:06:31

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

代码语言:javascript
复制
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还适用于引用类型:

代码语言:javascript
复制
using S = int &;
using T = decltype(std::declval<S>());
using U = decltype(*(S *)nullptr);  // fails

当类型不是引用类型时,declval会给出一个右值类型,而nullptr会给出一个左值。

票数 29
EN

Stack Overflow用户

发布于 2013-02-02 20:45:30

不,declval<T>()(*(T*)nullptr)不一样。而且decltype(expr.bar)decltype((expr.bar))是不一样的。

前一个比较比较表达式。后一次使用decltype检查表达式,前一次使用decltype检查expr.bar的声明类型。因此,您必须对decltype操作数的用法进行整理,以便对这些类型进行有用的比较,您会发现它们是不同的。

代码语言:javascript
复制
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值。

代码语言:javascript
复制
// T1: decltype((*(B*)0).a)
// T2: decltype(((*(B*)0).a))

在这两种类型中,第一个decltype给出了由表达式命名的成员的类型。该成员的类型为A,因此T1A。第二个decltype生成表达式的类型,如果表达式是左值,则由&修改;如果表达式是x值,则由&&修改。表达式是一个左值,所以T2A&

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14657092

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档