首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >auto与decltype的关系

auto与decltype的关系
EN

Stack Overflow用户
提问于 2011-07-29 15:25:44
回答 5查看 4K关注 0票数 35

代码语言:javascript
复制
auto x = initializer;

等同于

代码语言:javascript
复制
decltype(initializer) x = initializer;

代码语言:javascript
复制
decltype((initializer)) x = initializer;

或者两者都不是?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-07-29 15:32:41

decltype还会考虑表达式是rvalue还是lvalue

Wikipedia says

由decltype表示的类型可以与由auto.推导的类型不同。

代码语言:javascript
复制
#include <vector>
int main()
{
    const std::vector<int> v(1);
    auto a = v[0];        // a has type int
    decltype(v[0]) b = 1; // b has type const int&, the return type of
                        // std::vector<int>::operator[](size_type) const
    auto c = 0;           // c has type int
    auto d = c;           // d has type int
    decltype(c) e;        // e has type int, the type of the entity named by c
    decltype((c)) f = c;  // f has type int&, because (c) is an lvalue
    decltype(0) g;        // g has type int, because 0 is an rvalue
}

这在很大程度上解释了重要的区别。注意decltype(c)decltype((c))是不一样的!

有时,autodecltype以协作的方式协同工作,例如在下面的示例中(取自wiki,并做了一些修改):

代码语言:javascript
复制
int& foo(int& i);
float foo(float& f);

template <class T>
auto f(T& t) −> decltype(foo(t)) 
{
  return foo(t);
}

维基百科对decltype的进一步explains the semantics如下:

与sizeof运算符类似,decltype的操作数未求值。非正式地,decltype(e)返回的类型推导如下:

  • 如果表达式e引用局部或命名空间范围内的变量、静态成员变量或函数参数,则结果是该变量或参数的声明类型
  • 如果e是函数调用或重载运算符调用,
  • (E)表示该值的声明返回类型如果e是左值,decltype(e)是T&,其中T是e的类型;如果e是r值,则结果是T

这些语义是为了满足泛型库编写者的需要而设计的,同时对新手程序员来说也是直观的,因为decltype的返回类型总是与源代码中声明的对象或函数的类型完全匹配。更正式地说,规则1适用于无括号的id表达式和类成员访问表达式。对于函数调用,推导出的类型是静态选择的函数的返回类型,由重载解析规则确定。示例:

代码语言:javascript
复制
const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1; // type is const int&&
decltype(i) x2; // type is int
decltype(a->x) x3; // type is double
decltype((a->x)) x4; // type is const double&

后两次decltype调用之间存在差异的原因是,带括号的表达式(a->x)既不是id表达式,也不是成员访问表达式,因此不表示命名表达式。表达式是左值,其推导类型是“对表达式类型的引用”,或const object.Because &。

票数 37
EN

Stack Overflow用户

发布于 2011-07-29 16:07:52

这是行不通的(而且很难看):

代码语言:javascript
复制
decltype([]() { foo(); }) f = []() { foo(); };

鉴于

代码语言:javascript
复制
auto f = []() { foo(); };

将要。

票数 9
EN

Stack Overflow用户

发布于 2011-07-29 15:50:34

那得看情况。autodecltype服务不同的目的,所以它们不是一对一的映射。

auto的规则最容易解释,因为它们与模板参数推导的规则相同。我不会在这里详述它们,但请注意,auto&auto&&也是一些可能的用途!

然而,decltype有几种情况,您已经在上面说明了其中一些情况(摘自n3290,7.1.6.2简单类型说明符dcl.type.simple),我将其分为两类:

当使用标准所称的“不带括号的id表达式或不带括号的类成员访问”

  • rest时!

非正式地说,decltype既可以操作名称(第一种情况),也可以操作表达式。(按照形式和语法,decltype对表达式进行操作,因此可以将第一种情况看作是一种改进,而将第二种情况看作是一个通用的情况。)

当使用带有decltype的名称时,您将获得该实体的声明类型。例如,decltype(an_object.a_member)是出现在类定义中的成员的类型。另一方面,如果我们使用decltype( (an_object.a_member) ),我们就会发现自己处于一个包罗万象的情况下,我们正在检查表达式的类型,就像它在代码中出现的那样。

因此,如何涵盖您的问题的所有情况:

代码语言:javascript
复制
int initializer;
auto x = initializer; // type int
// equivalent since initializer was declared as int
decltype(initializer) y = initializer;
代码语言:javascript
复制
enum E { initializer };
auto x = initializer; // type E
// equivalent because the expression is a prvalue of type E
decltype( (initializer) ) y = initializer;
代码语言:javascript
复制
struct {
    int const& ializer;
} init { 0 };
auto x = init.ializer; // type int
// not equivalent because declared type is int const&
// decltype(init.ializer) y = init.ializer;
// not equivalent because the expression is an lvalue of type int const&
// decltype( (init.ializer) ) y = init.ializer;
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6869888

复制
相关文章

相似问题

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