为什么要了解类型推断?
C++98
在c++98的年代,只有模板才有类型推断,如果你不使用模板,那么你完全不需要理解类型推断。
C++11
在C++11中,类型推断在模板之外被大量应用。
- auto
- lambda captures
- function return
- decltype
想要熟练的使用上述新特性,那么就必须要了解类型推断的规则。
C++14
在C++14中,对类型推断又有了进一步的扩展。
- decltype(auto)
- lambda init captures
规则
在进行类型推断时,大家始终要记得一点,我们要推断的是两个类型,而非一个!
- T :这是推断的类型
- ParamType : 基于T,但是和T经常不一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template <typename T> void f1(T param) { }
template <typename T> void f2(T& param) { }
template <typename T> void f4(T* param) { }
template <typename T> void f4(T&& param) { }
|
C++98
在C++98中,对于模板的类型推断,可以分为两条规则:
C++11
在C++11中,可以分为六条规则:
- template
- lambda captures
- lambda return
- decltype
- auto
C++14
在C++14中,新增的扩展使用的还是上述六条规则:
- decltype(auto)
- lambda init captures
规则详解
template
T
丢弃CVR(const、volatile、reference),剩下的就是T的类型
当传入的是函数名或者数组名时,T会是函数指针或数组指针
不支持大括号初始化,因为大括号初始化没有类型
因为当param类型为T时,表示param将会是重新定义的一个全新的变量,与传递进来的变量应该彼此独立,所以T不能是引用,引用需要丢弃!一个全新的变量,其CV修饰符应该有自身显示定义,不应该继承其它变量的修饰符,所以CV修饰符应该丢弃。
1 2 3 4 5 6 7 8
| template <typename T> void f1(T param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
void test(int) {}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void test_f1() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "value" << std::endl; f1(x); f1(cx); f1(rx); f1(rcx); f1(px); f1(pcx); f1(cpx); f1(22);
f1(test); f1(arr); }
|
T&/T*
T&
丢弃引用,剩下的就是T的类型(继承CV)
当传入的是函数名或者数组名时,T会是函数引用或数组引用
因为param的类型是T&,已经有引用了,所以当传进来的变量是引用时,应该忽略引用;param是引用时,赋值是指向外部的变量本身,所以CV描述符不应该丢弃。
1 2 3 4 5 6 7 8
| template <typename T> void f2(T& param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
void test(int) {}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void test_f2() { int x = 22; const int cx = x; int& rx = x; int&& rx2 = 22; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "reference" << std::endl; f2(x); f2(cx); f2(rx); f2(rcx); f2(px); f2(pcx); f2(cpx); f2(rx2); f2(test); f2(arr); }
|
const T&
当显示声明CV修饰符时,丢弃CV
1 2 3 4 5
| template <typename T> void f3(const T& param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void test_f3() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; std::cout << "const reference" << std::endl; f3(x); f3(cx); f3(rx); f3(rcx); f3(px); f3(pcx); f3(cpx); f3(22); }
|
T*
丢弃指针,丢弃CV,剩下的就是T的类型
因为param的类型是T*,已经有指针了,所以当传进来的变量是指针时,应该忽略指针;param是指针就表明是一个全新的变量,其CV修饰符应该有自身显示定义,不应该继承其它变量的修饰符,所以CV修饰符应该丢弃。
1 2 3 4 5 6
| template <typename T> void f4(T* param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| void test_f4() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; std::cout << "pointer" << std::endl; f4(px); f4(pcx); f4(cpx); }
|
T&&
表达式为左值时,T为表达式类型(丢弃引用后)的左值引用;表达式为右值时,T为表达式类型。(继承CV)
注意:param看起来是右值引用,但并不一定是右值引用,只有当表达式为右值时,param才是右值引用
1 2 3 4 5
| template <typename T> void f7(T&& param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| void test_f7() { int x = 22; const int cx = x; int& rx = x; int&& rx2 = 22; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; std::cout << "universal reference" << std::endl; f7(x); f7(cx); f7(rx); f7(rx2); f7(rcx); f7(px); f7(pcx); f7(cpx); f7(22); }
|
const T&&
param一定是常量右值引用,只接收右值。
1 2 3 4 5
| template <typename T> void f8(const T&& param) { std::cout << "T = " << boost::typeindex::type_id_with_cvr<T>().pretty_name() << "; param = " << boost::typeindex::type_id_with_cvr<decltype(param)>().pretty_name() << std::endl; }
|
1 2 3 4
| void test_f8() { std::cout << "const universal reference" << std::endl; f8(22); }
|
auto
丢弃CVR(const、volatile、reference),剩下的就是auto的类型
当传入的是函数名或者数组名时,auto会是函数指针或数组指针
支持大括号初始化,分为直接赋值和拷贝赋值两种情况,c++17之前的编译器,所有推断出来的都是std::initializer_list,之后的编译器,拷贝赋值保持不变,直接赋值不支持多个元素,类型推断为第一个元素的类型
因为当变量类型为auto时,表示变量将会是重新定义的一个全新的变量,与传递进来的变量应该彼此独立,所以auto不能是引用,引用需要丢弃!一个全新的变量,其CV修饰符应该有自身显示定义,不应该继承其它变量的修饰符,所以CV修饰符应该丢弃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void test_f1() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "value" << std::endl; auto a_x = x; auto a_cx = cx; auto a_rx = rx; auto a_rcx = rcx; auto a_px = px; auto a_pcx = pcx; auto a_cpx = cpx; auto a_22 = 22;
auto a_test = test; auto a_arr = arr;
auto a_init = {1, 2, 3}; auto a_init3 = {1}; auto a_init4{1}; }
|
auto&/auto*
auto&
丢弃引用,剩下的就是auto的类型(继承CV)
当传入的是函数名或者数组名时,T会是函数引用或数组引用
因为变量的类型是auto&,已经有引用了,所以当传进来的变量是引用时,应该忽略引用;变量是引用时,赋值是指向外部的变量本身,所以CV描述符不应该丢弃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void test_f2() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "reference" << std::endl; auto& a_x = x; auto& a_cx = cx; auto& a_rx = rx; auto& a_rcx = rcx; auto& a_px = px; auto& a_pcx = pcx; auto& a_cpx = cpx;
auto& a_test = test; auto& a_arr = arr; }
|
const auto&
当显示声明CV修饰符时,丢弃CV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void test_f3() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "const reference" << std::endl; const auto& a_x = x; const auto& a_cx = cx; const auto& a_rx = rx; const auto& a_rcx = rcx; const auto& a_px = px; const auto& a_pcx = pcx; const auto& a_cpx = cpx; const auto& a_22 = 22;
const auto& a_test = test; const auto& a_arr = arr; }
|
auto*
丢弃指针,丢弃CV,剩下的就是auto的类型
因为变量的类型是auto*,已经有指针了,所以当传进来的变量是指针时,应该忽略指针;变量是指针就表明是一个全新的变量,其CV修饰符应该有自身显示定义,不应该继承其它变量的修饰符,所以CV修饰符应该丢弃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void test_f4() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "pointer" << std::endl; auto* a_px = px; auto* a_pcx = pcx; auto* a_cpx = cpx;
auto* a_test = test; auto* a_arr = arr; }
|
auto&&
表达式为左值时,auto为表达式类型(丢弃引用后)的左值引用;表达式为右值时,auto为表达式类型。(继承CV)
注意:auto变量看起来是右值引用,但并不一定是右值引用,只有当表达式为右值时,才是右值引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void test_f7() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "universal reference" << std::endl; auto&& a_x = x; auto&& a_cx = cx; auto&& a_rx = rx; auto&& a_rcx = rcx; auto&& a_px = px; auto&& a_pcx = pcx; auto&& a_cpx = cpx; auto&& a_22 = 22; }
|
const auto&&
只接收右值,一定是右值引用。
1 2 3 4
| void test_f8() { std::cout << "const universal reference" << std::endl; const auto&& a_22 = 22; }
|
lambda capture
reference
引用捕捉,使用模板T&规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void test_f1() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "reference capture" << std::endl; auto lam = [&x] {}; auto lam2 = [&cx] {}; auto lam3 = [&rx] {}; auto lam4 = [&rcx] {}; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| { class __lambda_16_14 { public: inline void operator()() const { } private: int & x; public: __lambda_16_14(int & _x) : x{_x} {} }; __lambda_16_14 lam = __lambda_16_14(__lambda_16_14{x}); class __lambda_17_15 { public: inline void operator()() const { } private: const int & cx; public: __lambda_17_15(const int & _cx) : cx{_cx} {} }; __lambda_17_15 lam2 = __lambda_17_15(__lambda_17_15{cx}); class __lambda_18_15 { public: inline void operator()() const { } private: int & rx; public: __lambda_18_15(int & _rx) : rx{_rx} {} }; __lambda_18_15 lam3 = __lambda_18_15(__lambda_18_15{rx}); class __lambda_19_15 { public: inline void operator()() const { } private: const int & rcx; public: __lambda_19_15(const int & _rcx) : rcx{_rcx} {} }; __lambda_19_15 lam4 = __lambda_19_15(__lambda_19_15{rcx}); }
|
value
值捕捉,使用模板T规则,但是继承CV!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void test_f2() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "value capture" << std::endl; auto lam = [x] {}; auto lam2 = [cx] {}; auto lam3 = [rx] {}; auto lam4 = [rcx] {}; auto lam5 = [px] {}; auto lam6 = [pcx] {}; auto lam7 = [cpx] {}; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| { class __lambda_16_14 { public: inline void operator()() const { } private: int x; public: __lambda_16_14(int & _x) : x{_x} {} }; __lambda_16_14 lam = __lambda_16_14(__lambda_16_14{x}); class __lambda_17_15 { public: inline void operator()() const { } private: const int cx; public: __lambda_17_15(const int & _cx) : cx{_cx} {} }; __lambda_17_15 lam2 = __lambda_17_15(__lambda_17_15{cx}); class __lambda_18_15 { public: inline void operator()() const { } private: int rx; public: __lambda_18_15(int & _rx) : rx{_rx} {} }; __lambda_18_15 lam3 = __lambda_18_15(__lambda_18_15{rx}); class __lambda_19_15 { public: inline void operator()() const { } private: const int rcx; public: __lambda_19_15(const int & _rcx) : rcx{_rcx} {} }; __lambda_19_15 lam4 = __lambda_19_15(__lambda_19_15{rcx}); class __lambda_20_15 { public: inline void operator()() const { } private: int * px; public: __lambda_20_15(int * _px) : px{_px} {} }; __lambda_20_15 lam5 = __lambda_20_15(__lambda_20_15{px}); class __lambda_21_15 { public: inline void operator()() const { } private: const int * pcx; public: __lambda_21_15(const int * _pcx) : pcx{_pcx} {} }; __lambda_21_15 lam6 = __lambda_21_15(__lambda_21_15{pcx}); class __lambda_22_15 { public: inline void operator()() const { } private: int *const cpx; public: __lambda_22_15(int *const _cpx) : cpx{_cpx} {} }; __lambda_22_15 lam7 = __lambda_22_15(__lambda_22_15{cpx}); }
|
init capture
初始化捕捉,使用auto规则。
C++14的扩展,在std=c++11时也可使用,但是会报警告warning: initialized lambda captures are a C++14 extension [-Wc++14-extensions]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void test_f3() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "init capture" << std::endl; auto lam = [x = x] {}; auto lam2 = [cx = cx] {}; auto lam3 = [rx = rx] {}; auto lam4 = [rcx = rcx] {}; auto lam5 = [px = px] {}; auto lam6 = [pcx = pcx] {}; auto lam7 = [cpx = cpx] {}; auto lam8 = [&x = x] {}; auto lam9 = [&cx = cx] {}; auto lam10 = [&rx = rx] {}; auto lam11 = [&rcx = rcx] {}; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
| { class __lambda_16_14 { public: inline void operator()() const { } private: int x; public: __lambda_16_14(int & _x) : x{_x} {} }; __lambda_16_14 lam = __lambda_16_14(__lambda_16_14{x}); class __lambda_17_15 { public: inline void operator()() const { } private: int cx; public: __lambda_17_15(const int & _cx) : cx{_cx} {} }; __lambda_17_15 lam2 = __lambda_17_15(__lambda_17_15{cx}); class __lambda_18_15 { public: inline void operator()() const { } private: int rx; public: __lambda_18_15(int & _rx) : rx{_rx} {} }; __lambda_18_15 lam3 = __lambda_18_15(__lambda_18_15{rx}); class __lambda_19_15 { public: inline void operator()() const { } private: int rcx; public: __lambda_19_15(const int & _rcx) : rcx{_rcx} {} }; __lambda_19_15 lam4 = __lambda_19_15(__lambda_19_15{rcx}); class __lambda_20_15 { public: inline void operator()() const { } private: int * px; public: __lambda_20_15(int * _px) : px{_px} {} }; __lambda_20_15 lam5 = __lambda_20_15(__lambda_20_15{px}); class __lambda_21_15 { public: inline void operator()() const { } private: const int * pcx; public: __lambda_21_15(const int * _pcx) : pcx{_pcx} {} }; __lambda_21_15 lam6 = __lambda_21_15(__lambda_21_15{pcx}); class __lambda_22_15 { public: inline void operator()() const { } private: int * cpx; public: __lambda_22_15(int * _cpx) : cpx{_cpx} {} }; __lambda_22_15 lam7 = __lambda_22_15(__lambda_22_15{cpx}); class __lambda_23_15 { public: inline void operator()() const { } private: int & x; public: __lambda_23_15(int & _x) : x{_x} {} }; __lambda_23_15 lam8 = __lambda_23_15(__lambda_23_15{x}); class __lambda_24_15 { public: inline void operator()() const { } private: const int & cx; public: __lambda_24_15(const int & _cx) : cx{_cx} {} }; __lambda_24_15 lam9 = __lambda_24_15(__lambda_24_15{cx}); class __lambda_25_16 { public: inline void operator()() const { } private: int & rx; public: __lambda_25_16(int & _rx) : rx{_rx} {} }; __lambda_25_16 lam10 = __lambda_25_16(__lambda_25_16{rx}); class __lambda_26_16 { public: inline void operator()() const { } private: const int & rcx; public: __lambda_26_16(const int & _rcx) : rcx{_rcx} {} }; __lambda_26_16 lam11 = __lambda_26_16(__lambda_26_16{rcx}); }
|
decltype
decltype对类型非常敏感,针对标识名和表达式的推断规则是不一样的。
1 2 3 4 5
| int x = 22;
std::cout << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype((x))>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(*&x)>().pretty_name() << std::endl;
|
标识名
对于标识名,得到声明的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void test_f1() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int&& rrx = 22; int arr[3]; std::cout << "decltype name" << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(x)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(cx)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(rx)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(rcx)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(px)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(pcx)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(cpx)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(test)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(arr)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(rrx)>().pretty_name() << std::endl; }
|
表达式
亡值
表达式值为亡值,类型为T&&。
1 2 3 4 5
| void test_f2() { int x = 22; std::cout << "decltype expr" << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(std::move(x))>().pretty_name() << std::endl; }
|
左值
表达式值为左值,类型为T&。
1 2 3 4 5 6
| void test_f2() { int x = 22; std::cout << "decltype expr" << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype((x))>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(*&x)>().pretty_name() << std::endl; }
|
纯右值
表达式值为纯右值,类型为T。
1 2 3 4 5 6 7
| void test_f2() { int x = 22; std::cout << "decltype expr" << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(22)>().pretty_name() << std::endl; std::cout << boost::typeindex::type_id_with_cvr<decltype(std::shared_ptr<int>())>().pretty_name() << std::endl; }
|
function return
lambda function
使用模板T的规则,去掉CVR,剩下的就是函数返回类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void test_f1() { int x = 22; const int cx = x; int& rx = x; const int& rcx = cx; int* px = &x; const int* pcx = &cx; int* const cpx = &x; int arr[3]; std::cout << "lambda function return" << std::endl; auto lam = [x] { return x; }; auto lam2 = [cx] { return cx; }; auto lam3 = [rx] { return rx; }; auto lam4 = [rcx] { return rcx; }; auto lam8 = [&x = x] { return x; }; auto lam9 = [&cx = cx] { return cx; }; auto lam10 = [&rx = rx] { return rx; }; auto lam11 = [&rcx = rcx] { return rcx; }; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| { class __lambda_16_14 { public: inline int operator()() const { return x; } private: int x; public: __lambda_16_14(int & _x) : x{_x} {} }; __lambda_16_14 lam = __lambda_16_14(__lambda_16_14{x}); class __lambda_17_15 { public: inline int operator()() const { return cx; } private: const int cx; public: __lambda_17_15(const int & _cx) : cx{_cx} {} }; __lambda_17_15 lam2 = __lambda_17_15(__lambda_17_15{cx}); class __lambda_18_15 { public: inline int operator()() const { return rx; } private: int rx; public: __lambda_18_15(int & _rx) : rx{_rx} {} }; __lambda_18_15 lam3 = __lambda_18_15(__lambda_18_15{rx}); class __lambda_19_15 { public: inline int operator()() const { return rcx; } private: const int rcx; public: __lambda_19_15(const int & _rcx) : rcx{_rcx} {} }; __lambda_19_15 lam4 = __lambda_19_15(__lambda_19_15{rcx}); class __lambda_20_15 { public: inline int operator()() const { return x; } private: int & x; public: __lambda_20_15(int & _x) : x{_x} {} }; __lambda_20_15 lam8 = __lambda_20_15(__lambda_20_15{x}); class __lambda_21_15 { public: inline int operator()() const { return cx; } private: const int & cx; public: __lambda_21_15(const int & _cx) : cx{_cx} {} }; __lambda_21_15 lam9 = __lambda_21_15(__lambda_21_15{cx}); class __lambda_22_16 { public: inline int operator()() const { return rx; } private: int & rx; public: __lambda_22_16(int & _rx) : rx{_rx} {} }; __lambda_22_16 lam10 = __lambda_22_16(__lambda_22_16{rx}); class __lambda_23_16 { public: inline int operator()() const { return rcx; } private: const int & rcx; public: __lambda_23_16(const int & _rcx) : rcx{_rcx} {} }; __lambda_23_16 lam11 = __lambda_23_16(__lambda_23_16{rcx}); }
|
auto
返回类型是auto时,使用auto规则。
C++11
在C++11上,只能通过返回值后置来实现,局限太大。
1 2 3 4 5
| template <typename U, typename T> auto Add(U u, T t) -> decltype(u + t) { auto val = u + t; return val; }
|
C++14
在C++14后只需要返回类型写auto就可以了。
1 2 3 4
| auto lookupvalue(const int index) { static std::vector<int> values = {1, 2, 3}; return values[index]; }
|
decltype(auto)
返回类型是decltype(auto)时,使用decltype规则。
1 2 3 4
| decltype(auto) lookupvalue2(const int index) { static std::vector<int> values = {1, 2, 3}; return values[index]; }
|
1 2 3 4 5
| decltype(auto) lookupvalue4(const int index) { static std::vector<int> values = {1, 2, 3}; auto val = values[index]; return (val); }
|