主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以(甚至不可能)表示之的问题。
正如sizeof操作符一样,decltype亦不需对操作数求值
规则:
若表达式e指向一个普通变量或函数参数,那么返回类型即为该变量(或参数)的“声明类型”;
若e是一个左值,则decltype(e)将返回T&,其中T为e的类型;
若e是一个右值引用,则返回值为T&&;
正如sizeof操作符一样,decltype亦不需对操作数求值
规则:
若表达式e指向一个普通变量或函数参数,那么返回类型即为该变量(或参数)的“声明类型”;
若e是一个左值,则decltype(e)将返回T&,其中T为e的类型;
若e是一个右值引用,则返回值为T&&;
若e是一个纯右值,则返回值为T。
1、类型查询:decltype(表达式)
int i;
struct C
{
int i;
double d;
};
// 使用推断的类型定义新的变量,确保两者类型一致
decltype(i) i1;
cout << typeid(i1).name() << endl; // int
C *c = new C;
decltype(c->i) i2;
cout << typeid(i2).name() << endl; // int
decltype(c->d) d2;
cout << typeid(d2).name() << endl; // double
delete c;
// const、pointer、reference
double&& d = 10; // 右值引用
float fval = 1.1;
const float& f = fval;
const int* ic = &i; // == int const*; point to (const) int
int *const ci = &i; // const pointer, point to int
// decltype保留const、引用性质
decltype(d) d1 = 30; // di: double&&, 必须初始化
decltype(f) f1 = fval; // f1: const float&, 必须初始化
decltype(ic) ic1; // ic1: const int *, 底层const
decltype(ci) ci1 = &i; // ci1: int *const, 顶层const, 必须初始化
int ival = 12;
// f1 = 15; // error, 不能给常量赋值
// ci1 = &ival; // error, 不能给常量赋值
// *ic1 = 15; // error, 不能给常量赋值
// typeid推断的“缺陷”:忽略掉const、引用性质
// 当作用指针时忽略掉顶层const而保留底层const
cout << typeid(d1).name() << endl; // double,但di: double&&
cout << typeid(f1).name() << endl; // float,但f1: const float&
cout << typeid(ic1).name() << endl; // int const*
cout << typeid(ci1).name() << endl; // int *
2、 模板函数的返回值占位
// 模板函数的返回值占位:使用auto与decltype关键字配合
template <class T, class U>
auto add(T t, U u) ->decltype(t+u)
{
return t+u;
}
auto r = add(1, 1.0);
cout << typeid(r).name() << endl; // double