auto自动推导
有几点注意
auto不声明为指针, 也可以推导出指针类型
int t=0;
auto t_1=&t;
auto* t_2=&t;
static_assert( is_same_v<decltype(t_1), decltype(t_2)> );
当不声明为指针或引用时, 会把表达式的const volatile属性丢掉
否则保留,
//p没声明为指针或引用, 丢掉cv(const volatile)限定
const volatile int a=1;
auto p=a;
static_assert( is_same_v<int, decltype(p)> );
//声明为引用, 保留cv
const int b=1;
auto &q=b;
static_assert( is_same_v<const int&, decltype(q)> );
//以下两种方式都能推导出为指针 保留cv
const int *c= nullptr;
auto r=c;
static_assert( is_same_v<const int*, decltype(r)> );
const int d=1;
auto z=&d;
static_assert( is_same_v<const int*, decltype(z)> );
auto不可以用于非静态成员变量, 不可定义数组 ,不可用作为函数参数
class A
{
auto a=0; //不能用于非静态成员
};
int arr[10];
auto t1[10]=arr; //不能加方括号声明为数组
auto t2=arr; //但可以不加括号直接推导为数组
void fun(auto a=1){} //不能用于函数参数
可以作为lambda表达式的参数
auto f=[](auto x){cout<<( x )<<endl;};
f(1);
可以用于静态成员变量,但如果这样用的话就得同时初始化, 而静态成员变量初始化需加上inline(c++17)
class A
{
inline static auto a=0; //静态成员
};
decltype
对于函数调用, 推导的是返回值, 但如果返回值是纯右值,则抛弃cv限定
const int &f1(); //左值
const int &&f2(); //x值
const int f3(); //纯右值
static_assert(is_same_v<const int &, decltype(f1())>);
static_assert(is_same_v<const int &&, decltype(f2())>);
static_assert(is_same_v<int, decltype(f3())>); //抛弃const
decltype(exp)
decltype推导规则
1: exp是标识符, 类访问表达式, decltype(exp)和exp类型一致
2: exp是函数调用, decltype(exp)和返回值的类型一致
3: 其他情况, 若exp左值, 结果为该类型的左值引用, 否则和该类型一致
对于规则2如上面所示
若推导的是加括号形式如decltype((x)), 用规则3得以下结果
class B
{
public:
int i;
};
const B b={};
//此处没括号,exp=b.i,用规则1 为B::i的类型
decltype(b.i) c2=1;
static_assert(is_same_v<int, decltype(c2)>);
//此处有括号,exp=(b.i)为其他情况,且b.i为左值, 推导出为左值引用(还保留了b的const)
decltype((b.i)) c1=1;
static_assert(is_same_v<const int&, decltype(c1)>);