快速业务通道

What are you,Anyway?

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
里,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 Compiler

为了处理这种情况,我们必须清晰的提示编译器:

这个nested name 是type name。如下:

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

在这里,我们使用关键字typename 来告诉编译器后面跟着的name,是type name。这样使得编译器可以正确的分析template。注意:我们告诉编译器:ElemT而不是T,是Type name。当然,编译器也能够知道T也是type name。同样,如果我们这样写:

typename A::B::C::D::E

这样,我们就相当于告诉编译器,E是type name。当然,如果模板函数传入的类型不满足template分解要求的话,会导致一个编译时刻的编译错误。

struct Z {
// no member named ElemT...
};
Z aZ;
//...
aFuncTemplate( aZ ); // error! no member Z::ElemT
aFuncTemplate( anX ); // error! X::ElemT is not a type name
aFuncTemplate( states ); // OK. PtrList<State>::ElemT is a type name

现在,我们可以重写fill()模板函数,

void fill( Cont &c, typename Cont::ElemT a[], int len ) { // OK
for( int i = 0; i < len; ++i )
c.insert( a[i] );
}

Gotcha: Failure to Employ typename with Permissive Compilers

注意:

使用typename 要求 嵌入 type name,如果编译器不能得到足够的信息的话,在模板的外部使用typename是非法的。

PtrList<State>::ElemT elem; // OK

typename PtrList<State>::ElemT elem; // error!

在模板的上下文中,这是很常见的错误。考虑一个在模板,在它内部实现,在编译时刻,从两个类型中选出一个,例如:

Select<cond,int,int *>::R r1; // OK
typename Select<cond,int,int *>::R r2; // error!
//...
}

由于编译器可以获得所有模板参数的信息,因此,甚至不需要在Select前写typename。如果,用模板重写f(),我们就可以使用typename。

template <typename T>
void f() {
Select<cond,int,int *>::R r1; // #1: OK, typename not required
typename Select<cond,int,int *>::R r2; // #2: superfluous
Select<cond,T,T *>::R r3; // #3: error! need typename
typename Select<cond,T,T *>::R r4; // #4: OK
//...
}

在情况2中,typename,可以不写,这样是可以的。

最有问题的是情况3,很多编译器都能察觉这个错误,将把这个嵌入的R解释为type name(的确它是一个type name,但是没有希望它解释为type name)以后,如果,这段代码出现在标准编译器上,那么会被查出错误的。因为这个原因,当你用C++模板编程,如果你必须使用非标准编译器的,你最好使用高级标准编译器,来检查你的代码。

Intermezzo: Expanding Monostate Protopattern

在模板问题上,我们先停顿一下,让我们看看搜索技术。 当我们想避免Monostate常常是Singleton的很好替代技术。当为了避免全局变量带来的麻烦时,Monostate是Singleton的很好替代品。

class Monostate {
public:
int getNum() const { return num_; }
void setNum( int num ) { num_ = num; }
const std::str

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号