member template
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的更多相关文章
- C++惯用法:通过成员模板实现隐式转换(Coercion 强迫 by Member Template)
Intent To increase the flexibility of a class template's interface by allowing the class template to ...
- C++泛型编程:template模板
泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础. 所谓template,是针对“一个或多个尚未明确的类型”所编写的函数或类. 使用template时,可以显示的或隐示的将 ...
- 模板(Template)
最近阅读google chromium base container stack_container代码,深刻感觉到基础知识不扎实. // Casts the buffer in its right ...
- check member function
template<typename T> struct has_member_foo11 { private: template<typename U> static auto ...
- CHECK MEMBER TYPE
检查类里是否存在某种类型的几种方法,以检查xxx类型为例:方法1: template<class T> class has_member_type_Type { ]; }; templat ...
- C++ Template Operator
#include <iostream> #include <string> #include <deque> #include <stdexcept> ...
- C++ Template 编程,泛型编程练习
#include <iostream> #include <string> #include <deque> #include <stdexcept> ...
- c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)
tokenization与parsing 解析模板之类型的依赖名称 Dependent Names of Templates Example One Example Two Example Three ...
- [c++] Templates
Template是编译时多态.所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态. Function Template A function template is a p ...
随机推荐
- 关于tp.5.0角色管理导致的创建角色登陆报错问题解决!
今天用tp 5.0的时候,遇到一个问题,就是在利用超级管理员创建管理员角色时,角色账号密码登陆报错的问题 解决方法如下 htaccess文件修改如下 <IfModule mod_rewrite. ...
- Jquery / js 判断数据类型方法(限制文本框类型输入)
当想要判断文本框中的值是否为自己想要的类型时,可以通过一些方法作出判断,这里对于光标离开文本框时判断文本框中输入的是否是数值类型,如果不是,做出提示 $("#WORKYEARS") ...
- 史航416第九次作业&总结
一.知识点总结: 1.二维数组定义的形式:类型名 数组名[行长度] [列长度] 例如:int a[3][2]:定义一个二维数组a,3行2列,6个元素: 2.二维数组引用的形式:类型名 数组名[行下标] ...
- IPython, Notebook, NumPy, SciPy, matplotlib 和其它
安装这些工具pip install ipython pip install notebookpip install numpypip install scipypip install matplotl ...
- Myeclipse2016部署tomcat服务(别的服务类似)配置环境
1.在工具MyEclipse的项目管理菜单中,右单机找Properties或者快捷键alt+enter,(或者直接搜索Runtimes)myEclipse/Targeted Runtimes 2.ne ...
- Java file read & write
1. read public static void readfile(String filepath) { BufferedReader br = null; try { String sCurre ...
- sqlite的简介
第一步: 第二步,建立桥接文件 随便创建一个类,语言选择oc,然后它会问你是否创建桥接模式,然后你选择是就可以了 那个类可以删除了 在那份桥接文件中加入一句话#import <sqlite3.h ...
- 第三方登录 QQ 错误码100044(提示 该应用非官方正版应用)
当你碰到这个问题的时候,不要着急,你的功能已经走通了,代码没有问题. 100044 原因: 1.首先确定你的包名和签名,跟申请第三方平台的是一个.(真心吐槽一下,接盘侠不好当,尤其是没有交接的) 2. ...
- EF 连接MySQL 数据库 保存中文数据后乱码问题
EF 连接MySQL 数据库 保存中文数据后乱码问题 采用Code First 生成的数据库,MySQL数据库中,生成的表的编码格式为***** 发现这个问题后,全部手动改成UTF8(图是另一个表的 ...
- servlet总结
什么是Servlet Tomcat容器等级 手工编写第一个Servlet 使用MyEclipse编写Servlet Servlet生命周期 Servlet常用对象,且与Jsp九大内置对象的关系 Ser ...