1、当且仅当类模板的参数相同时,你才能对类实体对象相互赋值,即将一个实体对象整体赋值给另外一个实体对象。不能将一种类型的实体对象赋值给另外一种实体对象。如:

Stack<int> intStack1,intStack2;

Stack<double> doubleStack;

intStack1 = intStack2;//OK:两个stack有相同的型别

intStack1 = doubleStack;//ERROR:两个stack没有相同的型别

default assignment需要运算符两边拥有相同的型别。

但是,只要将assignment运算符定义在类中为一个模板,就可以实现不同型别对象的赋值运算。型别不同,但是可以隐式转换。

template<typename T1>

class Stack

{

private:

std::deque<T1> elems;

public:

...

template<typename T2>

Stack<T1> & operator= (Stack<T2> const &);

};

assignment运算符定义如下所示:

template <typename T1>

template <typename T2>

Stack<T1>& Stack<T1>::operator=(stack<T2> const & op2)

{

if((void*)this == (void*)&op2)

{

return *this;

}

Stack<T2> tmp(op2);

elems.clear();

while(!tmp.empty())

{

elems.push_front(tmp.top());

tmp.pop();

}

return *this;

}

2、template template parameter双重模板参数

一个模板参数本身可以类模板。

为了使用其他类型的容器,Stack必须两次指定元素类型:一次是元素类型本身,一次是容器

Stack<int, std::vector<int> > vStack; //int stack,以vector为容器

如果使用双重模板参数,则可以如下定义:只需要指明元素类型,无需指明容器类型

Stack<int, std::vector> vStack;//int stack,以vector为容器

为了实现这种特性,需要将第二个模板参数定义为双重模板参数

template <typename T, template< typename NAME> class cont = std::queue >

class Stack{

private:

cont<T> elems;

...};

和之前的定义差别在于将第二个参数定义为类模板参数:

template< typename NAME> class cont

其默认值为std::queue;这个参数必须是一个类模板,并且由第一个参数完成实体化:cont<T> elems;

本例是用第一个模板参数来实体化第二个模板参数。但是,在实际运用时,可以使用类模板中的任意类型来实体化一个双重模板参数。

普通的模板参数可以用class来代替typename,但是上面的cont不可以用class来代替typename,因为cont是一个类类型,

template <typename T, template< typename NAME> typename cont = std::queue >

class Stack{

private:

cont<T> elems;

...};

由于双重模板参数中的参数并未使用,所以在定义的时候可以讲参数名称去掉:

template <typename T, template< typename > class cont = std::queue >

class Stack{

private:

cont<T> elems;

...};

所有类成员函数定义时,也必须指定其第二个模板参数为双重模板参数:

template <typename T, template< typename > class cont >

void Stack<T,cont>::push(T const &elem)

{

elems.push(elem);

}

函数模板不允许有双重模板参数。

3、如果你直接使用上面的stack声明进行编译,编译器可能会报错:默认值std::queue不符合双重模板参数CONT的要求。问题在于CONT不但必须是个模板,而且其参数必须严格匹配它所替换的双重模板参数的参数。双重模板形参的默认值不会被考虑,因此如果不给出默认值的引数值时,编译器会认为匹配失败。

问题在于标准程序库中的std::queue 模板不只有一个参数。第二个参数是一个配置器allocator,它虽然有预设值,但是当它被用来匹配CONT的参数时,其预设值被编译器强行忽略。

因此,可以从新定义Stack:

template <typename T, template< typename ELEM, typename ALLOC = std::allocator<ELEM> > class cont = std::queue >

class Stack{

private:

cont<T> elems;

...};

即使进行上述修改,VC仍然可能编译错误。可以讲成员elems的定义修改为cont<T,std::allocator<T> > elems;

由于ALLOC实际并未使用,因此也可以讲其省略,stack定义如下:

template <typename T, template< typename ELEM, typename = std::allocator<ELEM> > class cont = std::queue >

class Stack{

private:

cont<T> elems;

public:

void push(T const & );

template <typename T2, template< typename ELEM2, typename = std::allocator<ELEM2> > class cont2 >

Stack<T,cont>& operator=(Stack<T2,cont2> const &);

...};

template <typename , template< typename , typename > class cont >

void Stack<T, CONT>::push(T const &elem)

{

elems.push(elem);

}

template <typename T, template< typename , typename > class cont >

template <typename T2, template< typename , typename > class cont2 >

Stack<T,CONT>& Stack<T,CONT>::operator=(Stack<T2,CONT2> const &op2)

{

...

}

member template的更多相关文章

  1. C++惯用法:通过成员模板实现隐式转换(Coercion 强迫 by Member Template)

    Intent To increase the flexibility of a class template's interface by allowing the class template to ...

  2. C++泛型编程:template模板

    泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础. 所谓template,是针对“一个或多个尚未明确的类型”所编写的函数或类. 使用template时,可以显示的或隐示的将 ...

  3. 模板(Template)

    最近阅读google chromium base container stack_container代码,深刻感觉到基础知识不扎实. // Casts the buffer in its right ...

  4. check member function

    template<typename T> struct has_member_foo11 { private: template<typename U> static auto ...

  5. CHECK MEMBER TYPE

    检查类里是否存在某种类型的几种方法,以检查xxx类型为例:方法1: template<class T> class has_member_type_Type { ]; }; templat ...

  6. C++ Template Operator

    #include <iostream> #include <string> #include <deque> #include <stdexcept> ...

  7. C++ Template 编程,泛型编程练习

    #include <iostream> #include <string> #include <deque> #include <stdexcept> ...

  8. c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)

    tokenization与parsing 解析模板之类型的依赖名称 Dependent Names of Templates Example One Example Two Example Three ...

  9. [c++] Templates

    Template是编译时多态.所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态. Function Template A function template is a p ...

随机推荐

  1. Android菜鸟成长记16 -- JSON的解析

    JSON的定义  一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据 ...

  2. excel将单元格格式由数字转为文本

    由于python读取excel数据时,整数总会变成浮点数,例如1会变成1.0,这时可以通过将excel里面的数字转化为文本,再读取出来就不会变成浮点数了.还有一种情况是excel里面的数字是由公式计算 ...

  3. 未能正确加载“RoslynPackage”包

    一打开新建程序或者打开项目就报错,原因是安装的组件或者模板丢失或者有问题,在这一过程加载组件必定会产生错误,以下为解决方法: 1.重命名以下文件夹C:\Users\moonlight\Local Se ...

  4. auth用户认证库

    关于auth库,建议如下:1. ion_auth,基于Redux重写而成,非常不错的认证库,国外用的很多,几个最新的ci2.0.2基础上的开源系统(如doveforum)都用它,支持ci 2.0和以上 ...

  5. 向 Git 服务器添加 SSH 公钥

    . . . . . 在网上很少找到文章有提到如何将自己的 Git 远程仓库配置成可以通过 SSH 公钥方式认证的,而几乎清一色都是告诉你怎么通过 web 界面向 GitHub 添加 SSH 公钥.LZ ...

  6. ASP.NET MVC4中@model使用多个类型实例的方法

    转http://blog.csdn.net/hulihui/article/details/48199897

  7. [刘阳Java]_MyBatis_映射文件的常用标签总结_第5讲

    MyBatis中常用标签的总结,简单给出自己的总结 MyBatis映射文件中的标签使用介绍1.<select>:用于编写查询语句用的标签 id:表示当前<select>标签的唯 ...

  8. FormatMessage与GetLastError配合使用,排查windows api调用过程中的错误

    前一段时间在学习windows api调用过程中,遇到过一些调用错误或者程序没能显示预期的结果,或者直接出现vc运行时错误. 这对新手来说是司空见惯的事,因为不太熟悉难免会出错,出错的信息如果能显示很 ...

  9. 构造 & 析构 & 匿名对象‍

    ‍以前仅知道创建对象,但对匿名对象的了解基本为0. 通过阅读google chromium源代码 中关于 log 的使用,查阅相关资料,了解了一下匿名对象,予以记录. 什么是匿名对象‍ 匿名对象可以理 ...

  10. LVS_DR模式构建配置

    一.环境准备 lvs负载均衡器 系统:centos6.8 ip:192.168.2.203 vip:192.168.2.17 web服务器RS1 系统:centos6.8 ip:192.168.2.2 ...