C++ decltype和auto

C++11开始改变了C++98中关键字auto的定义,使得C++可以在一些情况下不用写长长的变量类型,例如:

std::vector<SomeType> a;
for(auto p = a.begin(); p != a.end(); p++){}
或
for(auto&p : a){} // c++11 for

这里auto省去了冗长的变量类型的书写,尤其是当“SomeType”是由多层模板得到的时候,变量名的长度简直就是噩梦,如果这个变量是一个库中的函数返回值则更加糟糕,有可能你完全不知道这是个什么类型。

auto还可以接复杂的lambda表达式,例如:

auto lambda = [](int x) { return x + 3; };

decltype是C++11引进的新关键字,和之前typeid看起来有点像但是好用的多

decltype可以获取一个变量或表达式的类型并直接使用,例如:

int a = 1;
decltype(a) b = a + 1;
double c = 2.3;
decltype(a + c) d;  // d的类型取决于a+c的类型

说到这里,如果想打印一个变量类型名,则使用typeid().name(),和decltype没有关系,例如:

int a = 1;
std::cout << typeid(a).name() << std::endl;

auto不可以做为函数参数,但可以借助模板函数和decltype关键字实现省略不知道(或太长不想写)的参数类型。

如一个模板函数如下:

template <typename Itr>
decltype(auto) func(std::function<void(Itr p, double& x> lambda, Itr begin = 0, Itr end = 0){return ...;}

则可以这样使用:

func<decltype(a.begin())>([](auto p, double& x){}, a.begin(), a.end());

func<>()的<>中本应该输入a.begin()的具体类型,但由于太长,想省略,直接使用auto是不被允许的,但是加上这个decltype就可以了。

函数的返回值类型则可以用decltype(auto)的方式表达(只有返回值可以这样用,函数参数是不可以的),返回类型取决于return的是什么。

值得注意的是,函数的第一个参数lambda表达式中的参数类型可以使用auto,这也是auto可以做为参数出现的唯一情况,并且只能出现在函数调用的时候,函数声明和定义的时候依然需要使用Itr类型。

C++17还支持auto做为模板类型(尚未测试)

template<auto n> // C++17 auto parameter declaration
auto f() -> std::pair<decltype(n), decltype(n)> // auto can't deduce from brace-init-list
{
    return {n, n};
}

 

Reference  Reference

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

17 + 1 =