fre*_*low 34 c++ type-inference decltype auto c++11
是
auto x = initializer;
Run Code Online (Sandbox Code Playgroud)
相当于
decltype(initializer) x = initializer;
Run Code Online (Sandbox Code Playgroud)
要么
decltype((initializer)) x = initializer;
Run Code Online (Sandbox Code Playgroud)
还是两个?
Naw*_*waz 37
decltype也考虑表达式是否为rvalue或lvalue.
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
}
Run Code Online (Sandbox Code Playgroud)
这几乎解释了这一重要差异.注意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);
}
Run Code Online (Sandbox Code Playgroud)
维基百科进一步解释了语义的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&
Run Code Online (Sandbox Code Playgroud)
后两个decltype调用之间差异的原因是括号表达式(a-> x)既不是id表达式也不是成员访问表达式,因此不表示命名对象.因为表达式是左值,它的推导类型是"引用表达式的类型",或const double&.
这不起作用(并且很难看):
decltype([]() { foo(); }) f = []() { foo(); };
Run Code Online (Sandbox Code Playgroud)
而
auto f = []() { foo(); };
Run Code Online (Sandbox Code Playgroud)
将.
这取决于.auto并且decltype服务于不同的目的,因此他们不会一对一地映射.
规则auto是最容易解释的,因为它们与模板参数推导相同.我不会在这里扩展它们,但请注意auto&并且auto&&也是一些可能的用途!
decltype 但是有几个案例,其中一些你已经在上面说明了(信息和引用取自n3290,7.1.6.2简单类型说明符[dcl.type.simple]),我将它分为两类:
非正式地说,我会说decltype可以对任何一个名称(对于第一种情况)或表达式进行操作.(正式并且根据语法decltype对表达式进行操作,因此将第一种情况视为一种改进,将第二种情况视为一种全能.)
使用带有decltype的名称时,您将获得该实体的声明类型.因此,例如decltype(an_object.a_member),它出现在类定义中的成员类型.另一方面,如果我们使用,decltype( (an_object.a_member) )我们发现自己处于catch-all的情况下,我们正在检查表达式的类型,就像它出现在代码中一样.
因此,如何涵盖所有问题的案例:
int initializer;
auto x = initializer; // type int
// equivalent since initializer was declared as int
decltype(initializer) y = initializer;
Run Code Online (Sandbox Code Playgroud)
enum E { initializer };
auto x = initializer; // type E
// equivalent because the expression is a prvalue of type E
decltype( (initializer) ) y = initializer;
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3504 次 |
| 最近记录: |