auto和decltype的关系 [英] The relationship between auto and decltype

查看:37
本文介绍了auto和decltype的关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

auto x = 初始值设定项;

相当于

decltype(initializer) x = initializer;

decltype((initializer)) x = initializer;

还是两者都没有?

解决方案

decltype 还要考虑表达式是 rvalue 还是 lvalue .

维基百科说

<块引用>

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

#include <向量>int main(){const std::vectorv(1);汽车 a = v[0];//a 的类型为 intdecltype(v[0]) b = 1;//b 的类型为 const int&,返回类型为//std::vector::operator[](size_type) const自动 c = 0;//c 的类型为 int自动 d = c;//d 的类型为 int声明类型(c)e;//e 的类型为 int,即 c 命名的实体的类型decltype((c)) f = c;//f 的类型为 int&,因为 (c) 是一个左值声明类型(0)g;//g 的类型是 int,因为 0 是一个右值}

这几乎解释了重要的区别.注意 decltype(c)decltype((c)) 不一样!

有时autodecltype 以协作方式一起工作,例如在以下示例中(取自wiki,并稍作修改):

int&foo(int& i);浮动 foo(float& f);模板自动 f(T&t) ->声明类型(foo(t)){返回 foo(t);}

维基百科进一步解释了decltype的语义如下:

<块引用>

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

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

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

const int&&富();国际我;结构 A { 双 x;};const A* a = new A();声明类型(foo())x1;//类型是 const int&&声明类型(i)x2;//类型是intdecltype(a->x) x3;//类型是doubledecltype((a->x)) x4;//类型是 const double&

<块引用>

后两次调用decltype不同的原因是括号表达式(a->x)既不是id-表达式也不是成员访问表达式,因此不表示命名对象.因为表达式是一个左值,所以它的推导类型是对表达式类型的引用",或者const double&.

Is

auto x = initializer;

equivalent to

decltype(initializer) x = initializer;

or

decltype((initializer)) x = initializer;

or neither?

解决方案

decltype also considers whether the expression is rvalue or lvalue .

Wikipedia says,

The type denoted by decltype can be different from the type deduced by auto.

#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
}

That pretty much explains the imporant difference. Notice decltype(c) and decltype((c)) are not same!

And sometime auto and decltype works together in a cooperative way, such as in the following example (taken from wiki, and modified a bit):

int& foo(int& i);
float foo(float& f);

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

Wikipedia further explains the semantics of decltype as follows:

Similarly to the sizeof operator, the operand of decltype is unevaluated. Informally, the type returned by decltype(e) is deduced as follows:

  • If the expression e refers to a variable in local or namespace scope, a static member variable or a function parameter, then the result is that variable's or parameter's declared type
  • If e is a function call or an overloaded operator invocation, decltype(e) denotes the declared return type of that function
  • Otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e; if e is an rvalue, the result is T

These semantics were designed to fulfill the needs of generic library writers, while at the same time being intuitive for novice programmers, because the return type of decltype always matches the type of the object or function exactly as declared in the source code. More formally, Rule 1 applies to unparenthesized id-expressions and class member access expressions. For function calls, the deduced type is the return type of the statically chosen function, as determined by the rules for overload resolution. Example:

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&

The reason for the difference between the latter two invocations of decltype is that the parenthesized expression (a->x) is neither an id-expression nor a member access expression, and therefore does not denote a named object.Because the expression is an lvalue, its deduced type is "reference to the type of the expression", or const double&.

这篇关于auto和decltype的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆