1.定义
auto关键字要求必须初始化,编译器才能推到出变量类型。
decltype关键字,用于编译时推导一个表达式的类型。
2.语法格式:
decltype(expression)
类似于sizeof运算符,在编译器完成的类型推导,不会计算表达式的值。
int x = 0;
decltype(x) y = 1; // y -> int
decltype(x+y) z = 0; // z -> int
const int & i = x;
decltype(i) j = y; // j -> const int &
const decltype(z) *p = &z; // p -> const int *
decltype(z) * m = &z; // m -> int *
decltype(m) * n = &m; // n -> int **
3.使用规则:
3.1exp如果是标识符、类访问表达式、结果与标识符、类表达式相同(保留cv属性)
3.2exp如果是函数调用,则和返回值类型一致
3.3exp如果是一个左值,则以exp类型的左值引用一致,否则和exp本身一致
// 标识符和类型访问表达式
class Foo
{
public:
static const int Number = 0;
int x;
};
int n = 0;
volatile const int & x = n;
decltype(n) a = n; // a -> int
decltype(x) b = n; // b -> volatile int &
decltype(Foo::Number) c = n; // c -> const int 丢失static
Foo f;
decltype(foo.x) d = 0; // d -> int
// 函数调用
const int & fun_a(); // 左值引用
const int && fun_b(); // 右值引用
const int func_c(); // 基本类型纯右值
const Foo func_d(); // 返回类类型纯右值
decltype(fun_a) a = x; // a -> const int &
decltype(fun_b) b = 0; // b -> const int &&
decltype(fun_c) c = 0; // c -> int 丢失const
decltype(fun_d) d = Foo(); // d -> const Foo 保留const
// 表达式和加法运算
struct Foo
{
int x;
};
const Foo foo = Foo{};
decltype(foo.x) a = 0; // a -> int
decltype((foo.x)) b = 0; // b -> const int 括号表达式结果为左值引用,故是const int &
int m = 0;
int n = 0;
decltype(n+m) c = 0; // c -> int
decltype((n+m)) d = 0; // d -> int & 括号表达式为左值引用,故为int &
4.返回类型后置语法(跟踪返回类型)
template <typename T,typename U>
auto add(T t,U,u) -> decltype(t+u)
{
return t + u;
}
int & foo(int & i);
float foo(float & f);
template<typename T>
auto func(T & val) -> decltype(foo(val))
{
return foo(val);
}