跳至主要内容

template template parameter

挺拗口的,不过TTP其实只是模板参数的进一步抽象。就像指针,指向指针的指针那样,这个比喻可能不太恰当,不过大概是这个意思啦。
下面的代码定义了一个模板类,第一个模板参数是接受类型的参数,第二个是接受模板类型的参数。
template <typename T, template <typename ELEM> class CONT = std::deque>
class Stack {
private:
CONT
<T> elems;
public:

}
;
单独将第二个参数提取出来看,template <> class CONT 只是一个很平常的模板,这便是定义一个模板类型的模板参数的语法,因为只是为了说明CONT是个模板,所以ELEM可以省去,即template class CONT,就算加上了,ELEM也不能当作类型使用,这实际上是一个dummy参数。有人要问了,typename能省吗?这可不行,template<> class CONT是实例化的模板,template class CONT是模板定义,两者不同。所以啦,为了让std::deque参数能直接写成std::deque,绕了这么一大圈。
虽然typename与class在template参数定义中常常等价,
但是template class CONT = std::deque> 是有效的,
而template typename CONT = std::deque>是无效的,会引起编译错误。
为什么呢?因为CONT被定义为模板,而模板需要实例化才能使用,即CONT。这么用的多半是class,而且我们在Stack定义中也是这么实现的,如此一来,typename便使得类型匹配处引起编译错误了,虽然不知道是否会出现可以使用typename的情况,书中确实提到Template template parameters for function templates are not allowed,看起来似乎只能使用class关键字。
不过上面的代码在使用时仍然不能通过编译,因为TTP的类型匹配不会使用默认参数,因此,对标准库的deque而言,第二个带默认值的参数allocator是必须明确定义的,不然类型不匹配。于是代码改成下面这样:
template <typename T,
template
<typename ELEM,
typename ALLOC
= std::allocator<ELEM> > class CONT = std::deque>
class Stack {

}
;
这里ALLOC同样是可以省略的。
...头有点大了,还慢慢学吧

评论

此博客中的热门博文

知识管理的原则

寻找PKM时,看到这样一个贴子,感觉有一些原则比较有启发作用,其实重要的是方法,其次是合适的工具。所谓原则,对不同人来说也不是绝对,适合自己的就好。 个人知识管理的29个原则(转) 1、持续的学习成为个人生存和发展的基础。持续学习不一定能带来成功,但不学习一定失败;  2、信息和知识爆炸,在一段时间和时期内,学习的内容必须聚焦。起码要在一个领域内成为专家。  3、你应该学习的内容取决于你的价值观、特长、个性和目标。  4、你必须学会如何有效的评估信息和知识,所以你必须根据你的价值观、特长、个性和目标确立自己对信息和知识的“过滤器”;  5、人是知识获取的重要渠道,所以你应该知道谁最擅长什么?遇到问题时知道可以向谁学习和请教;  6、你牛了你的朋友也一定牛,建立人际资源的基础是自己的知识基础、个性和激情、自己优势的合理展示和帮助别人的意愿;  7、人际关系需要维护;捷径是找到那些愿意共享自己朋友资源的人,你也应该做这样的人;  8、信息如果不经过处理,不能称为知识。所以你存储的知识起码你应该简单看过、知道是在讲什么;  9、信息和知识存储前应该尽可能做规范化的工作,例如你做的摘要、感触、觉得最有价值的部分、将来能做什么用等等;  10、建立自己的分类字典,而不是每次想起什么就建立什么样的文件夹或者标签。分类字典,持之以恒坚持,适当调整;  11、知识存储中分类不宜过宽,过宽则等于没有分类;分类不宜过深,过深后你就不会再去看;  12、充分利用各种工具,尤其是web2.0工具做知识存储和获取工作;  13、知识存储时适当共享,听取和收集别人的意见和建议;  14、有意识的做知识显性化的工作,既方便知识传播也促进知识学习和建立人际网络;  15、知识传播中必须考虑传播的方式和效率;  16、不能用简单朴素的语言表述的知识证明你还没有深入理解;  17、多用举例子、讲故事的方法传播你的知识、见解。这个过程是你对知识的再深化过程;  18、你的知识传播的越广,你的影响力越大;  19、你的目的决定了你知识利用的方式。如果目的是要写论文,则你的知识就是明确、简洁的表达;如果是想要在市场上销售,就必须产品化、规范化或者专利化;  20、知识本身没有价值,只有被利用时才能展现其价值;  21、知识必须跟任务、项目结合起来才能发挥作用;  22、单独的一个主题的知识很难被很好的利用,...

Computer Systems: A Programmer's Perspective

Bryant, R.E所著的这本Computer Systems: A Programmer's Perspective,在国内翻译为《深入理解计算机系统》,由中国电力出版社2004出版,应该算是一本重量级的书了。从同学推荐到今天看完,足足花了有5个月的时间,虽然看得不深,但总的感觉还是不错,在这里就对它作一个总结吧。 Computer Systems表明这本书讲解的是计算机系统知识,但A Programmer's Perspective却又告诉我们它与其它书籍的不同之处,便是从程序员的角度,即偏向软件的角度,而不过多地涉及硬件内容。计算机系统本身就是一门涉及面广,内容繁多的学科,这本书不可避免地从各个角度讲解了这些内容。下面以我个人的观点进行一些总结。 第1章:计算机系统漫游 主要是对全书内容作了一个简要的概括。 第2章:信息的表示和处理 这一章主要讲解了整数与浮点数。虽然对于整数我们已经很熟悉了,但是在实际中仍会犯下各种各样的错误,书中对不同整型数间的转换及运算作出了很详细的论述。浮点数似乎一直是计算机书籍里不愿涉及的话题,对于想了解浮点数表示及浮点数运算的人来说,这部分关于浮点的描述可以作为一个很好的起点。 第3章 程序的机器级表示 对于任何一个希望了解底层的人来说,这一章可说是相当精彩的。本章主要讲解了IA32的指令集,因此以汇编为主,在控制流指令部分还将C语言及对应的汇编形式进行了对照,在调用部分还详细讲解了本地栈。最后为对浮点感兴趣的人准备了IA32中用于处理浮点的指令集。 第4章 处理器体系结构 这一章是本书中最接近硬件的部分了,从设计一个简单的处理器Y86出发并逐步完善它,一步步地引导读者理解处理器体系结构。虽然我们可能永远也不会自己设计处理器,但了解它是何工作的能有助我们理解整个计算机系统是如何工作的,比如对程序优化就很有帮助。本章首先给出了Y86的指令集,并使用一种硬件描述语言HCL对硬件的逻辑结构进行了描述,然后将指令分成取指、译码、执行、访存、写回、更新PC六个阶段,给出了每条指令的每一部分的操作内容,并对每一部分的硬件实现分别进行了讨论。显然,这种顺序的实现过程是低效的,本章的后面部分便围统着流水线的实现以及遇到的问题展开了论述。 第5章 优化程序性能 本章介绍了一些代码优化的内容,如前面所说,只有理解了处理器系...

MIPS中断在uboot下的实现

摘要:本文阐述了MIPS中断在u-boot下的整个实现过程,并对实践中遇到的问题进行了分析,特别分析了u-boot所采用的位置无关代码及汇编实现的特殊性,对类似应用具有较好的借鉴意义。 随着Linux嵌入式系统的广泛使用,使用uboot作为bootloader越来越多。u-boot发源于ppc架构8xx系列,对ppc架构的支持最为完善,而对其它架构的支持情况则要弱一些,以MIPS为例,目前的最新版本u-boot-2010.03仍然不支持异常和中断的处理。缺少中断机制带来了一些麻烦,比如不能支持统一的点灯规范,更重要的是在无中断的单任务环境下,协议栈缺乏有效的超时重传机制,在复杂的框上环境中,单板容易假死在boot中。 本文描述了MIPS架构中断在u-boot下的实现过程,并对遇到的问题进行了分析和总结。我们首先讨论了通用的异常处理过程,然后结合代码实现对异常处理代码进行了阐述,最后对调试过程中出现的问题进行了分析。u-boot有其自身的特点,本文同时也对位置无关代码进行了一定的分析。 中断处理在实现上并不复杂,其处理过程可以简单地划分为下面几个步骤: 1. 保存中断上下文 2. 处理中断并应答 3. 恢复中断上下文 4. 使能中断 这种处理方式比较简单,整个中断处理是在中断环境中完成的,没有中断嵌套。对于VxWorks这样的实时操作系统,需要允许高优先级中断抢占低优先级中断,因此它的处理步骤要复杂一些,在进入中断后,只保存少量的易失性寄存器,并尽早地开启中断。因为我们只需要实现简单的定时器,所以就按照最简单的方法实现。 MIPS CPU产生中断时,CPU跳转到EBASE+0x180或者0x200(取决于COP0 Cause.IV的设置。IV=1时,中断使用0x200入口,IV=0时,中断使用通用异常入口0x180)处开始执行中断处理程序。一般来说,异常向量处的大小都是受限的,MIPS也不例外,每个异常向量的大小不能超过0x80的长度,如果要在这里进行上下文保存,空间是不够的。惯例是在这里设一处跳转,到一个大小不受限的地方开始保存上下文。 上下文的保存可以分为两种实现,一种是使用当前任务的栈,一种是使用专门的栈,对于只工作在内核态的boot来说,这两者在使用上并无差别。理论上,开辟专门的栈可靠性更高,不容易被破坏。对于不同的架构,上下文的含义不同,对MIPS而言,上下...