What are you, Anyway?

滨江一角

滨江一角

2016-01-29 12:22

What are you, Anyway?,What are you, Anyway?

What are you, Anyway?
作者:Stephen C. Dewhurst 译者:陶章志

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/cyuyanjiaocheng/)

原文出处:http://www.cuj.com/documents/s=8464/cuj0308dewhurst/

在经过艰难的讨论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 获得实例化的模板信息。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/cyuyanjiaocheng/)

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] );
}

蹩脚的编译器

很遗憾的是,在这里我们有一个语法错误。编译器不能识别Cont::ElemT这个type name。问题是在fill()的上下文中,没有足够的信息让编译器知道ElemT是一个type name。在标准中规定,在这种情况下,认为nested name 不是type name。 现在刚刚开始,如果你没有理解,不要紧。我们来看看在不同的上下文中,编译器所获得的信息。首先,让我们来看看在没有模板的class的情况:
class MyContainer {
public:
typedef State ElemT;
//...
};

//...
MyContainer::ElemT *anElemPtr = 0;

由于编译器可以检测到MyContainer class的上下文确定有个ElemT的成员类型,从而可以确认MyContainer::ElemT确实是一个type name。在实例化的模板类中,其实,也跟这种情况一样简单。

typedef PtrList<State StateList;
//...
StateList::ElemT aState = 0;
PtrList<State::ElemT anotherState = 0;

对于编译器来说,一个实例化的模板类跟一个普通的类一样。在存储PtrList<State的nested name 和在MyContainer中是一样的,没有什么差别。在其他情况下,编译器也是这样检查上下文来看ElemT是不是type name。然而,当我们进入template的上下文后,事情就变得复杂了。因为在这,没有充分的准确信息。考虑下面的程序片断:

template <typename T
void aFuncTemplate( T &arg ) {
...T::ElemT...

当编译器遇到T::ElemT,它不知道这是什么。从模板的申明中,编译器知道,T是一个类型名。它通过::运算符也能猜测出T是一个类型名。但是,这就是所有编译器知道的。因为,这里没有关于T的更多的信息。例如:我们能够用PtrList来调用一个模板函数,在这里,T::ElemT将是一个Type name。

PtrList<State states;
//...
aFuncTemplate( states ); // T::ElemT is PtrList<State::ElemT
But suppose we were to instantiate aFuncTemplate with a different type?
struct X {
double ElemT;
//...
};
X anX;

//...
aFuncTemplate( anX ); // T::ElemT is X::ElemT

在这个例子中,T::ElemT是数据类型,不是type name。编译器将怎么办呢?在标准中规定,在这种情况下,编译器将认为nested name 不是type name。在将在上述fill()模板函数中导致一个语法错误。

Clue In the Compile

展开更多 50%)
分享

猜你喜欢

What are you, Anyway?

C语言教程 C语言函数
What are you, Anyway?

Do what you say,say what you do

电脑入门
Do what you say,say what you do

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

《闪点行动3:红河》图文流程攻略(Careful What You Wish For...)

电脑网络
《闪点行动3:红河》图文流程攻略(Careful What You Wish For...)

What is Mono?

电脑网络
What is Mono?

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

What is XAML?

电脑网络
What is XAML?

you know I love you,you know I miss you

电脑入门
you know I love you,you know I miss you

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

《忍者必须死2》新手必看攻略

《忍者必须死2》新手必看攻略

确定有穷自动机分析内核

确定有穷自动机分析内核
下拉加载更多内容 ↓