decltype关键字:
1.计算表达式的类型
sizeof操作符的值是一个整数,表示类型的长度(字节数)
typeid操作符的值是一个对象,其中包含了类型的信息
decltype操作符的值是一个类型,可用于其它对象的声明
1 #include <iostream> 2 #include <typeinfo> 3 using namespace std; 4 int main (void) { 5 int a = 0; 6 //int b = 1; 7 //auto b = a; 8 // b:int,decltype的值就是表达式的类型本身 9 decltype (a) b = 1; 10 cout << typeid (b).name () << endl; // i 11 // c:int,decltype只在编译期计算表达式的类型,不在运行期计算表达式的值 12 decltype (a++) c = 2; 13 cout << typeid (c).name () << endl; // i 14 cout << a << endl; // 0 15 int const& d = a; 16 // e:int const&,decltype会保留表达式的引用属性和CV限定 17 decltype (d) e = d; 18 cout << &e << ‘ ‘ << &a << endl; // 地址相同 19 /* e带有常属性 20 cout << ++e << endl; */ 21 // f:int,auto会丢弃表达式的引用属性和CV限定 22 auto f = d; 23 cout << &f << ‘ ‘ << &a << endl; // 地址不同 24 cout << ++f << endl; // 1 25 // g:int*,h:int**,decltype可以和指针联用 26 decltype (a) *g= &a, **h = &g; 27 cout << typeid (g).name () << endl; // Pi 28 cout << typeid (h).name () << endl; // PPi 29 // h---->g---->a 30 // int** int* int 31 // i:int const&,decltype可以和引用以及CV限定联用 32 decltype (a) const& i = a; 33 cout << &i << ‘ ‘ << &a << endl; // 地址相同 34 /* i带有常属性 35 cout << ++i << endl; */ 36 return 0; 37 }
2.对于函数表达式,decltype将返回该函数返回值的类型,对于左值表达式,decltype返回该表达式的左值引用
1 #include <iostream> 2 #include <typeinfo> 3 using namespace std; 4 int max (int x, int y) 5 { 6 return x < y ? y : x; 7 } 8 int* max (int* x, int* y) 9 { 10 return *x < *y ? y : x; 11 } 12 int const& min (int const& x, int const& y) 13 { 14 return x < y ? x : y; 15 } 16 int main (void) 17 { 18 int a = 123, b = 456; 19 decltype (max (a, b)) c; 20 cout << typeid (a).name () << endl; // i 21 decltype (max (&a, &b)) d = NULL; 22 cout << typeid (d).name () << endl; // Pi 23 // e:int& 24 decltype (++a) e = a; 25 --e; // --a; 26 cout << a << endl; // 122 27 // f:int 28 decltype (b++) f = b; 29 --f; 30 cout << b << endl; // 456 31 // g:int& 32 decltype (a = b) g = a; 33 --g; 34 cout << a << endl; // 121 35 // h:int 36 decltype (b + a) h = b; 37 --h; 38 cout << b << endl; // 456 39 // i:int 40 decltype (a) i = a; 41 // j:int& 42 decltype ((a)) j = a;//decltype的表达式如果是加上了括号的变量,结果将是引用 43 cout << &i << ‘ ‘ << &j << ‘ ‘ << &a << endl; 44 return 0; 45 }
注意:decltype((variable))(注意是双层括号)的结果永远是引用,
而decltype(variable)的结果只有当variable本身是一个引用时才是引用
3.何时使用decltype
1 #include <iostream> 2 #include <vector> 3 #include <list> 4 #include <map> 5 using namespace std; 6 template<typename C> 7 void print (C& c) { 8 for (decltype (c.begin ()) it = c.begin (); 9 it != c.end (); ++it) 10 cout << *it << ‘ ‘; 11 cout << endl; 12 } 13 int main (void) { 14 int ai[] = {10, 20, 30, 40, 50}; 15 vector<int> vi (ai, ai + 5); 16 print (vi); 17 list<int> const li (vi.begin (), vi.end ()); 18 print (li); 19 map<string, vector<int> > msv; 20 msv["张飞"].push_back (70); 21 msv["张飞"].push_back (85); 22 msv["赵云"].push_back (75); 23 msv["赵云"].push_back (90); 24 msv["关羽"].push_back (80); 25 msv["关羽"].push_back (95); 26 // . 27 // . 28 // . 29 // 此处省略15000行代码 30 // . 31 // . 32 // . 33 // int sum = 0; 34 decltype (msv)::mapped_type::value_type sum = 0; 35 for (size_t i = 0; i < msv["张飞"].size (); ++i) 36 sum += msv["张飞"][i]; 37 cout << sum << endl; 38 return 0; 39 }
4.auto和decltype结合使用,返回类型后置
1 #include <iostream> 2 #include <typeinfo> 3 using namespace std; 4 double foo (int arg) { 5 return arg / 2.0; 6 } 7 int foo (double arg) { 8 return int (arg * 2); 9 } 10 // 返回类型后置 11 template<typename T> 12 auto bar (T const& arg) -> decltype (foo (arg)) { 13 return foo (arg); 14 } 15 // 返回类型后置 16 template<typename T> 17 auto add (T const& x, T const& y) -> decltype (x + y) { 18 return x + y; 19 } 20 class Point { 21 public: 22 Point (int x, int y) : m_x (x), m_y (y) {} 23 void draw (void) const { 24 cout << "点(" << m_x << ‘,‘ << m_y << ‘)‘ << endl; 25 } 26 private: 27 int m_x, m_y; 28 }; 29 class Line { 30 public: 31 Line (Point const& p1, Point const& p2) : 32 m_p1 (p1), m_p2 (p2) {} 33 void draw (void) const { 34 cout << "线(" << ‘\t‘; 35 m_p1.draw (); 36 cout << ‘\t‘; 37 m_p2.draw (); 38 cout << ‘)‘ << endl; 39 } 40 private: 41 Point m_p1, m_p2; 42 }; 43 Line const operator+ (Point const& p1, Point const& p2) { 44 return Line (p1, p2); 45 } 46 int main (void) { 47 cout << bar (1) << endl; // 0.5 48 cout << bar (0.5) << endl; // 1 49 Point p1 (100, 200), p2 (300, 400); 50 Line line = add (p1, p2); 51 line.draw (); 52 return 0; 53 }