首页 / 软件开发 / C++ / What are you,Anyway?
What are you,Anyway?2010-05-19陶章志在经过艰难的讨论template metaprogramming很长时间后,返回到我们学习的开始。在这一部分,我们来了解模板编程的更为模糊的语法问题:在编译器没有充分的信息的情况下,怎样引导编译器进行分析。在这里,我们将讨论标准容器中用来消除歧义的“rebind”机制。同时,我们也将对一些潜在的模板编程技术进行热烈的讨论。甚至经验丰富的C++程序员,也常常被模板的复杂的语法所困扰。在所以模板语法中,我们首先要了解:消除编译器分析的歧义,是最基本的语法困惑。Types of Names, Names of Types让我们看看一个没有实现标准容器的模板例子,这个例子很简单。template <typename T>
class PtrList {
public:
//...
typedef T *ElemT;
void insert( ElemT );
private:
//...
};
常常模板类嵌入Type names信息,这样,我们就可以通过正确的nested name 获得实例化的模板信息。typedef PtrList<State> StateList;
//...
StateList::ElemT currentState = 0;
嵌入类型的ElenT允许我们可以,很容易的访问PtrList模板的所承认的元素类型。即使我们用State类型初始化PtrList,元素类型还将是State*。在其他一些情况下,PtrList 可以用指针元素实现。一个比较成熟的PtrList的实现,应该是可以随着初始化的元素类型而变化的。使用nested type,可以帮助我们封装PtrList,以免用户了解内部的实现。下面还有一个例子:template <typename Etype>
class SCollection {
public:
//...
typedef Etype ElemT;
void insert( const Etype & );
private:
//...
};
SCollection的实现跟PtrList一样,遵守标准命名的条款。遵守这些条款是有用的,这样我们就可以写出很多优雅的算法来使用这些容器(译注:像标准模板库一样)。例如:可以写一个如下的算法:用适当的元素类型来填充这个容器数组。template <class Cont>
void fill( Cont &c, Cont::ElemT a[], int len ) { // error!
for( int i = 0; i < len; ++i )
c.insert( a[i] );
}