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

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

问题描述

  auto x = initializer; 

相当于

  decltype(initializer)x = initializer; 

  decltype((initializer))x = initializer; 

或两者皆不?

解决方案 c> rvalue 或 lvalue / code>。



维基百科说


由decltype表示的类型可能与由auto推断的类型不同。 / p>



  #include< vector> 
int main()
{
const std :: vector< int> v(1);
auto a = v [0]; // a has type int
decltype(v [0])b = 1; // b有类型const int&,
的返回类型// std :: vector< int> :: operator [](size_type)const
auto c = 0; // c有类型int
auto d = c; // d有类型int
decltype(c)e; // e有类型int,由c
命名的实体的类型decltype((c))f = c; // f has type int&,因为(c)是一个左值
decltype(0)g; // g有类型int,因为0是一个右值
}

重要的差异。注意 decltype(c) decltype((c))不一样!



且有时自动 decltype 一起合作方式,例如在以下示例中(取自 wiki ,并修改了一些):

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

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

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


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




  • 如果表达式e指的是局部或命名空间范围,静态成员变量或函数参数,那么结果是变量或参数的声明类型

  • 如果e是函数调用或重载运算符调用,decltype(e)该函数的返回类型

  • 否则,如果e是一个左值,则decltype(e)是T&,其中T是e的类型;如果e是右值,则结果是T



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




  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 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天全站免登陆