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(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& b;
static int
c;
void foo()
decltype(a) //
decltype(this->a) //
decltype((*this).a) //
decltype(b) //
decltype(c) // int (static
members are treated as variables in namespace scope)
void bar() const
decltype(a) //
decltype(b) //
decltype(c)
// int
}
};
A aa;
const A& caa =
aa;
decltype(aa.a) // int
decltype(aa.b) //
decltype(caa.a) //
但内置操作符.*和->*适用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 {
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修飾符被忽略:
i = ...;
const int j = ...;
decltype(i)&
// int&. The redundant & is ok
const decltype(j) // const
int. The redundant const is ok
eg10 函數調用(Rule-2)
foo();
decltype(foo()) // int
float&
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)
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>()
"const int";
string Foo<int
&>()
return "int&";
string Foo<const int&>()
"const int&";
class A{};
Foo<A>()
return "A";
main()
int a;
int &b =
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;
<< "f: " << Foo<decltype(f)>() <<
F:\tmp>g++ decltype_eg1.cpp
-std=c++0x
F:\tmp>a.exe
a: int
b: int&
c: const
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.