是
auto x = initializer;等同于
decltype(initializer) x = initializer;或
decltype((initializer)) x = initializer;或者两者都不是?
发布于 2011-07-29 15:32:41
decltype还会考虑表达式是rvalue还是lvalue。
Wikipedia says,
由decltype表示的类型可以与由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
}这在很大程度上解释了重要的区别。注意decltype(c)和decltype((c))是不一样的!
有时,auto和decltype以协作的方式协同工作,例如在下面的示例中(取自wiki,并做了一些修改):
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)返回的类型推导如下:
这些语义是为了满足泛型库编写者的需要而设计的,同时对新手程序员来说也是直观的,因为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 object.Because &。
发布于 2011-07-29 16:07:52
这是行不通的(而且很难看):
decltype([]() { foo(); }) f = []() { foo(); };鉴于
auto f = []() { foo(); };将要。
发布于 2011-07-29 15:50:34
那得看情况。auto和decltype服务不同的目的,所以它们不是一对一的映射。
auto的规则最容易解释,因为它们与模板参数推导的规则相同。我不会在这里详述它们,但请注意,auto&和auto&&也是一些可能的用途!
然而,decltype有几种情况,您已经在上面说明了其中一些情况(摘自n3290,7.1.6.2简单类型说明符dcl.type.simple),我将其分为两类:
当使用标准所称的“不带括号的id表达式或不带括号的类成员访问”
非正式地说,decltype既可以操作名称(第一种情况),也可以操作表达式。(按照形式和语法,decltype对表达式进行操作,因此可以将第一种情况看作是一种改进,而将第二种情况看作是一个通用的情况。)
当使用带有decltype的名称时,您将获得该实体的声明类型。例如,decltype(an_object.a_member)是出现在类定义中的成员的类型。另一方面,如果我们使用decltype( (an_object.a_member) ),我们就会发现自己处于一个包罗万象的情况下,我们正在检查表达式的类型,就像它在代码中出现的那样。
因此,如何涵盖您的问题的所有情况:
int initializer;
auto x = initializer; // type int
// equivalent since initializer was declared as int
decltype(initializer) y = initializer;enum E { initializer };
auto x = initializer; // type E
// equivalent because the expression is a prvalue of type E
decltype( (initializer) ) y = initializer;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;https://stackoverflow.com/questions/6869888
复制相似问题