练习16.17
声明为typename的类型参数和声明为class的类型参数有什么不同(如果有的话)?什么时候必须使用typename?
解答:
http://blog.sina.com.cn/s/blog_62bfdb9c0100ja6w.html 这篇博文讲的很详细。
第一问:
没有什么不同
第二问:
1. template parameters(模板参数)时,class 和 typename 是可互换的。
2. typename 去标识 nested dependent type names,在 base class lists中或在一个 member initialization list中作为一个 base class identifier时除外。
练习16.18
解释下面每个函数模板声明并指出他们是否非法。更正你发现的每个错误。
(a) template <typename T, U, typename V> void f1(T, U, V);
(b) template <typename T> T f2(int &T);
(c) inline template <typename T> T foo(T, unsigned int*);
(d) template <typename T> f4(T, T);
(e) typedef char Ctype;
template <typename Ctype> Ctype f5(Ctype a);
解答:
(a) 非法。更正template <typename T, typename U, typename V> void f1(T, U, V);
(b)合法。在声明的时候,编译器会忽略形参的名字,template <typename T> T f2(int &);这就是编译器处理的声明,不过这个函数在调用的时候就需要显式声明类型了,否则编译器无法判断返回值的类型。
非法。这里感谢 隔壁的程序员 同学的勘误。这里编译器不会像我之前说的那样做。这里T是一个类型,而不是一个变量的名字。所以(b)中的参数列表只声明了参数类型,而没有添加形参名字。所以,在这里编译器会将int &T 当做一个类型进行处理,之后编译器发现这个类型自己没有办法进行翻译,所以就会报错。
(c) 非法。更正 template <typename T>inline T foo(T, unsigned int*);
(d) 非法,缺少返回类型的声明,更正template <typename T>void f4(T, T);
(e) 合法,这个可以参考一下“模板参数与作用域”(第593页)
练习16.19
编写函数,接受一个容器的引用,打印容器中的元素。使用容器的size_type和size成员来控制打印元素的循环。
解答:
template <typename T>
void print(const std::vector<T>& container){
typedef typename std::vector<T>::size_type size_type;
std::size_t size = container.size();
for (std::size_t i = 0; i != size; ++i){
std::cout << container[i] << std::endl;
}
}
template <typename Container>
void print(const Container& container){
typedef typename Container::size_type size_type;
std::size_t size = container.size();
auto it = container.begin()
for (size_t i = 0; it != container.end(); ++i){
std::cout << *it++ << std::endl;
}
}
练习16.20
重写上一题的函数,使用begin和end返回迭代器来控制循环。
解答:
template <typename T>
void print(const std::vector<T>& container){
for (auto it = container.begin(); it != container.end(); ++it){
std::cout << it << std::endl;
}
}
template <typename Container>
void print(const Container& container){
for (auto it = container.begin(); it != container.end(); ++it){
std::cout << it << std::endl;
}
}