练习16.42
对下面每个调用,确定T和val的类型:
template <typename T> void g(T&& val);
int i = 0; const int ci = i;
(a) g(i);
(b) g(ci);
(c) g(i * ci);
解答:
#include <iostream>
#include <type_traits>
template <typename T>
void g(T&& val){
typedef typename std::remove_reference<T>::type A;
typedef typename std::remove_reference<T&>::type B;
typedef typename std::remove_reference<T&&>::type C;
std::cout << std::boolalpha;
std::cout << "typedefs of int:" << std::endl;
std::cout << "A: " << std::is_same<const int,A>::value << std::endl;
std::cout << "B: " << std::is_same<const int,B>::value << std::endl;
std::cout << "C: " << std::is_same<int,C>::value << std::endl;
}
int i = 0;
const int ci = i;
int main(){
g(i = ci);
}
使用以上代码进行类型的判别
(a) 类型为int&
(b) 类型为 const int& int&
(c) 类型为 int&& const int&&(感谢 隔壁的程序员 同学的勘误)
关于 隔壁的程序员 提到的引用折叠规则,在 wiki 上有比较详细的介绍。
这里摘两句出来
【如果实参是类型A的左值,则模板参数T的类型为A&,形参类型为A&;】
【如果实参是类型A的右值,则模板参数T的类型为A&&,形参类型为A&&。】
【2015.05.12】
在评论中也有提到,这里的类型判断不会那么的容易。
今天,重新写了验证程序来验证这三个类型。
先上代码:
#include <iostream>
#include <type_traits>
using namespace std;
static int num;
template <typename T>
void g(T&& val){
cout << num++ << ":" << endl;
std::cout << std::boolalpha;
cout << "T's type is " << typeid(T).name() << endl;
cout << "T's type is const? " << is_const<T>::value << endl;
cout << "Is reference? " << is_reference<T&&>::value << endl;
cout << "Is left reference? " << is_lvalue_reference<T&&>::value << endl;
cout << "Is right reference? " << is_rvalue_reference<T&&>::value << endl;
}
int i = 0;
const int ci = i;
int main(){
cout << "i's type is " << typeid(i).name() << endl;
cout << "ci's type is " << typeid(ci).name() << endl;
cout << "i * ci's type is " << typeid(i * ci).name() << endl;
g(i);
g(ci);
g(i * ci);
}
C++11中,type_traits头文件中提供了很多对于类型判断的工具,详细跳转到 http://www.cplusplus.com/reference/type_traits/
i's type is intci's type is int
i * ci's type is int
0:
T's type is int
T's type is const? false
Is reference? true
Is left reference? true
Is right reference? false
1:
T's type is int
T's type is const? false
Is reference? true
Is left reference? true
Is right reference? false
2:
T's type is int
T's type is const? true
Is reference? true
Is left reference? false
Is right reference? true
以上是我在visual studio 2013上运行出来的结果。
结果很清楚了,我在之前的回答中,对于b,c的判断是错误的。(已经在上面更正)
再回头看这题,还是挺有意义的,希望这里的补充能帮到看到我博客的同学。
练习16.43
使用上一题定义的函数,如果我们调用g(i = ci), g的模板参数将是什么?
解答:
这里应该还是i传进去的时候的类型, int&。
练习16.44
使用与第一题中相同的三个调用,如果g的函数参数声明为T(而不是T&&),确定T的类型。如果g的函数参数是const T&呢?
解答:
当声明为T的时候,T的类型为int&。
当声明为const T&的时候,T的类型为int&。
练习16.45
给定下面的模板,如果我们对一个像42这样的字面常量调用g,解释会发生什么?如果我们对一个int类型的变量调用g呢?
template <typename T> void g(T&& val){vector<T> v;}
解答:
当使用字面常量,T将为int。
当使用int变量,T将为int&。编译的时候将会报错,因为没有办法对这种类型进行内存分配,无法创建vector<int&>.