1 第五章 技巧性基础知识
1.1 关键字typename
在标准化c++的过程中,引入typename是为了说明:模板内部的标识符可以是一个类型。下面举个例子:
template<typename T>
class MyClass{
typename T::SubType * ptr;
..
};
1.1.1 .templates构造
这个比较生僻一些,给个例子吧
template<int N>
void printBitset(std::bitset<N> const& bs)
{
std::cout<<bs.template to_string<char, std::char_traits<char>, std::allocator<char> >();
}
只有在编译器判断小于号(<)之前,存在依赖于模板的构造,才会出现这种问题。
1.2 使用this->
这个暂时不是很明白,需要等看了
1.3 成员模板
类成员也可以是模板,嵌套类和成员函数都可以作为模板。下面通过Stack<>的赋值运算符来索命这种能力的应用方法。
template<typename T>
class Stack{
...
public:
template<typename T2>
Stack<T>& operator=(Stack<T2> const&);
};
template<typename T>
template<typename T2>
Stack<T>& Stack<T>::operator=(Stack<T2> const& op2)
{
...
}
此处需要注意成员模板函数的声明和定义。
1.4 模板的模板参数
关于这个名词,以前一直没有理解。其实现在看来也比较简单,就是作为模板参数的参数,在定义的时候,就约定这个参数一定要是一个模板。
需要说明的是,vc6不支持该特定,vc7开始就支持了。
有了模板的模板参数之后,原来需要这样写的代码:
Stack<int, std::vector<int> > vStack;
现在可以改为这样:
Stack<int, std::vector> vStack;
所以在我看来,这个特性没有太大的用处,而且对于定义模板的人来说,还会增加很多的工作量。
原来的:
template<typename T, typename CONT=std::vector<T> >
class Stack{
...
};
现在就要改成:
template<typename T, typename <typename ELEM> class CONT=std::deque >
class Stack{
...
};
这还只是声明,在定义处还有许多烦人的东西。
这里由于我们没有用到ELEM,所以可以ELEM可以省略。
上面的这个class不能替换为typename;
1.4.1 模板的模板实参匹配
如果你尝试去编译上面提供的代码,就发发现有编译错误,这里涉及到一个模板的模板实参匹配问题。
如果模板的模板实参(譬如这里的std::deque)是一个具有参数A的模板,他将替换模板的模板参数(这里的CONT),而模板的模板参数是一个具有参数B的模板(这里为ELEM),匹配的过程要求参数A和参数B完全匹配;然而这里我们并没有考虑模板的模板实参的缺省模板参数,从而也就使B中缺少了这些参数值,当然也就无法精确匹配。
1.5 零初始化
任何未被初始化的局部变量都是一个不确定值。
所以,对于类模板内部的成员,最好在构造函数内的初始化列表内初始化这些成员。
1.6 使用字符串作为函数模板的实参
有时,把字符串传递给函数模板的引用参数会导致出人意料的运行结果。
template<typename T>
inline T const& max(T const& a, T const& b)
{
return a<b?:a;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::string s;
::max("apple", "peach"); //OK
::max("apple", "tomato");//ERROR
::max("apple", s); //ERROR
return 0;
}
对于其中
::max("apple", "tomato");//ERROR
为什么会出错,可能会有很多人不理解,我一开始也不理解,所以这里重点说明。
由于长度的区别,这些字符串属于不同的数组类型。也就是说,”apple”和”peach”具有相同的类型 char const[6];然而,”tomato”的类型则是:char const[7]。因此,只有第一个调用是合法的。
如果改为非引用的参数,你就可以使用长度不同的字符串来作为max()的参数。
产生这种结果的原因:对于非引用类型的参数,在实参演绎的过程中,会出现数组到指针的decay。
以后如果你遇到一个关于字符数组和字符穿指针之间不匹配的问题,你会意外地发现和这个问题有一定的相似之处。