C++0x引入了新的关键字decltype,它是一个操作符,用来取得表达式的类型,主要在泛型编程中使用。这里,简单介绍一下语法规则。
语法形式:decltype (expression) 其中,这里的括号必不可少(这点不同于sizeof操作符)。decltype(e)可看到是一个类型别名,并且不会对表达式e进行计算(即只有编译时行为而无运行时行为)。另外,不允许把decltype作用于一个类型,因为没有任何理由要这样做。
确定decltype(e)类型的规则如下: Rule-1. 如果e是一个标识符表达式或者类成员访问表达式,那么decltype(e)就是e所命名的实体的类型。如果没有此实体或者e命名了一个重载函数集,那么程序是ill-formed的。 Rule-2. 如果e是一个函数调用或者一个重载操作符调用(忽略e外面的括号),那么decltype(e)就是该函数的返回类型。 Rule-3. 否则,假设e的类型是T:如果e是一个左值,则decltype(e)就是T&;否则(e是一个右值),decltype(e)就是T。
举例分析如下(内容来自参考Ref1):
eg1 名字空间或局部作用域内的变量(Rule-1) int a; int& b = a; const int& c = a; const int d = 5; const A e;
(注:不能直接编译,这里写出来只是分析) decltype(a) // int decltype(b) // int& decltype(c) // const int& decltype(d) // const int decltype(e) // const A
但需要注意括号可能会影响结果,例如: decltype((a)); // int& (此时(a)表达式不满足Rule-1和Rule-2,应用Rule-3,而表达式(a)是一个左值,所以为int&)
eg2 函数形参(Rule-1) void foo(int a, int& b, float&& c, int* d) { decltype(a) // int decltype(b) // int& decltype(c) // float&& decltype(d) // int* }
eg3 函数类型(Rule-1) int foo(char); int bar(char); int bar(int);
decltype(foo) // int(char) decltype(bar) // error, bar is overloaded
但需要注意当形成函数指针时适用Rule-3: decltype(&foo) // int(*)(char) decltype(*&foo) // int(&)(char)
eg4 数据类型(Rule-1) int a[10]; decltype(a) // int[10]
eg5 成员变量(Rule-1) class A { int a; int& b; static int c; void foo() { decltype(a) // int decltype(this->a) // int decltype((*this).a) // int decltype(b) // int& decltype(c) // int (static members are treated as variables in namespace scope) } void bar() const { decltype(a) // int decltype(b) // int& decltype(c) // int } };
A aa; const A& caa = aa; decltype(aa.a) // int decltype(aa.b) // int& decltype(caa.a) // int
但内置操作符.*和->*适用Rule-3: decltype(aa.*&A::a) // int& decltype(aa.*&A::b) // illegal, cannot take the address of a reference member decltype(caa.*&A::a) // const int&
eg6 this(Rule-3) class X { void foo() { decltype(this) // X*,因为this是右值 decltype(*this) // X&,因为*this是左值 } void bar() const { decltype(this) // const X* decltype(*this) // const X& } };
eg7 指向成员变量和成员函数的指针(Rule-1) class A { int x; int& y; int foo(char); int& bar() const; };
decltype(&A::x) // int A::* decltype(&A::y) // error: pointers to reference members are disallowed (8.3.3 (3)) decltype(&A::foo) // int (A::*) (char) decltype(&A::bar) // int& (A::*) () const
eg8 字面值(Rule-3) (字符串字面值是左值,其它字面值都是右值) decltype("decltype") // const char(&)[9] decltype(1) // int
eg9 冗余的引用符(&)和CV修饰符 由于decltype表达式是一个类型别名,因此冗余的引用符(&)和CV修饰符被忽略: int& i = ...; const int j = ...; decltype(i)& // int&. The redundant & is ok const decltype(j) // const int. The redundant const is ok
eg10 函数调用(Rule-2) int foo(); decltype(foo()) // int float& bar(int); decltype (bar(1)) // float& class A { ... }; const A bar(); decltype (bar()) // const A const A& bar2(); decltype (bar2()) // const A&
eg11 内置操作符(Rule-3) decltype(1+2) // int (+ returns an rvalue) int* p; decltype(*p) // int& (* returns an lvalue) int a[10]; decltype(a[3]); // int& ([] returns an lvalue) int i; int& j = i; decltype (i = 5) // int&, because assignment to int returns an lvalue decltype (j = 5) // int&, because assignment to int returns an lvalue decltype (++i); // int& decltype (i++); // int (rvalue)
如何用程序验证decltype的结果?可以参考下面的程序对上面的分析结果进行验证: F:\tmp>type decltype_eg1.cpp #include <iostream> #include <string> using namespace std;
template <typename T> string Foo() { return "unknown"; }
template <> string Foo<int>() { return "int"; }
template <> string Foo<const int>() { return "const int"; }
template <> string Foo<int &>() { return "int&"; }
template <> string Foo<const int&>() { return "const int&"; }
class A{};
template <> string Foo<A>() { return "A"; }
int main() { int a; int &b = a; const int &c = a; const int d = 5; A e; double f;
cout << "a: " << Foo<decltype(a)>() << endl; cout << "b: " << Foo<decltype(b)>() << endl; cout << "c: " << Foo<decltype(c)>() << endl; cout << "d: " << Foo<decltype(d)>() << endl; cout << "e: " << Foo<decltype(e)>() << endl; cout << "f: " << Foo<decltype(f)>() << endl; }
F:\tmp>g++ decltype_eg1.cpp -std=c++0x
F:\tmp>a.exe a: int b: int& c: const int& d: const int e: A f: unknown
F:\tmp>gcc --version gcc (GCC) 4.3.0 20080305 (alpha-testing) mingw-20080502 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
参考资料: Ref1: Decltype (revision 6): proposed wording Ref2: Decltype (revision 7): proposed wording转自: http://www.cublog.cn/u/18517/showart_1664016.html
|