#include <iostream>
const int g_i=0;
const int & g_i_r = g_i;
const int foo(int){
return 0;
}
const int bar(int){
return 0;
}
class test{
public:
const double foo(int){return 0;}
const double bar(int){return 0;}
double val_=0;
double val2_=0;
const double val3_=0;
static const int n_;
};
test t;
const int test::n_=0;
char arr[10];
int&& g_rr=0;
const int& foo2(int){
static int kk;
return kk;
}
int main()
{
/
//规则一:简单id-expression规则
//如下例子,都是一些“简单id-expression”的例子,
//其decltype(e) 的推导,就是e的原始类型,包括cv修饰符也不丢。
//这一点,完全符合直觉。
//typeof(a0) == typeof(g_i) == const int
decltype(g_i) a0 = 0;
//typeof(pfbar) == typeof(foo) == const int (int)
decltype(foo) *pfbar = bar;
pfbar(123); //函数指针调用表达式
//typeof(pfbar2) == typeof(&foo) == const int (*)(int)
decltype(&foo) pfbar2 = bar;
pfbar2(123); //函数指针调用表达式
//typeof(pftestbar) == typeof(&test::foo) == const double (test::*) (int)
decltype(&test::foo) pftestbar=&test::bar;
(t.*pftestbar)(123);
//typeof(pm) == typeof(&test::val_) == int test::*
decltype(&test::val_) pm=&test::val2_;
t.*pm = 3.1415;
//typeof(a1) == typeof(test::val3_) == const double
decltype(test::val3_) a1=0;
//typeof(g_i_r) == typeof(a2) ==const int&
decltype(g_i_r) a2 = g_i;
//typeof(a3) == typeof(t.val3_) ==const int&
decltype(t.val3_) a3 =0;
//typeof(a4) == const int
decltype(test::n_) a4 =0;
//typeof(a5) == int[10]
decltype(arr) a5 = {1,2,3,4,5};
//
//规则二:lvalue, xvalue, pvalue表达式规则:
//如果一个表达式不是“简单id-expression”,
//你就要考察它到底是个什么表达式,三者必居其一.
//IF e ==> lvalue THEN decltype(e) ==> T&
//IF e ==> prvalue THEN decltype(e) ==> T
//IF e ==> xvalue THEN decltype(e) ==> T&&
//重要提示: cv修饰符会丢弃
//typeof(a6) == int
decltype(foo(123)) a6 =0;
a6=0; //丢cv, 所以不是const int
//typeof(a7) == double
decltype(t.foo(123)) a7 =0;
a7=0;
decltype(foo2(123)) a77 = 0;
int i=0;
int &j = i;
//typeof(a8)== int&
decltype(++i) a8=j;
//typeof(a9)== int
decltype(i++) a9=0;
//typeof(a10)== int&
decltype(++j) a10=i;
//typeof(a11)== int
decltype(j++) a11=0;
//typeof(a12)== int
decltype(1) a12 = 0;
//typeof(a13)== int&&
decltype(std::move(i)) a13=0;
//说明:xvalue也叫“即将消亡值”。我更愿意称它为"蝙蝠值"。
//字母x,好像蝙蝠展开的翅膀,x也好似四条腿。你看蝙蝠可以加入鸟类大军,因为它有翅膀,
//蝙蝠也可以加入兽类大军,因为它张了四条腿。xvalue如果加入右值大军,当然没有问题,
//因为它具有move语义。xvalue加入广义左值大军,也没有问题。为什么左值愿意接纳它呢?
//因为它具有Identity语义,你每次调std::move(i),好像来源都指的是同一个对象。
//这一点上,它与纯右值有重大差别, 与左值有重大相似。
//
//规则三:括号规则
//如果表达式e被加上括号,则decltype不再认为e为“简单id-expression”
//然后按照规则二推理
decltype((i)) h=j; //因为(i)是一个lvalue, 所以被推导为int&
decltype((std::move(i))) h2=0; //h2的类型是int&&
decltype((0)) h3=0; //h3的类型是int。而不是const int
return 0;
}