C++ 模板 template (双模板?)

2024-03-02

我想建立一个Stack类,因此用户将能够选择他想要使用哪个容器来实现Stack。例如,List/Vector.

部分代码:

stack.h

#ifndef STACK_H_
#define STACK_H_

template <typename T, template<typename T> class ContainerType>
class Stack{
    ContainerType<T> container;
public:
    Stack() : container(ContainerType<T>()){}

};

#endif /* STACK_H_ */

test.cpp

#include "stack.h"
#include <vector>

int main(){   
    Stack<int, std::vector<int> > stack;
    return 0;
}

嗯,它无法编译。我在线收到下一个错误:

Stack<int, std::vector<int> > stack;

Errors:

expected a class template, got `std::vector<int, std::allocator<int> >' test.cpp

invalid type in declaration before ';' token test.cpp

type/value mismatch at argument 2 in template parameter 
list for `template<class T, template<class T> class ContainerType> 
class Stack' test.cpp

‪

首先,它会是std::vector,没有别的,因为vector位于std命名空间,并且您要求一个模板 模板参数, while std::vector<int>不再是模板了。接下来,一个std::vector实际上需要two模板参数,一个用于类型,另一个用于分配器:

template <
    typename T,
    template<typename, typename> class ContainerType,
    typename Alloc = std::allocator<T>
>
class Stack{
  ContainerType<T, Alloc> container;
  // ...
};

// usage:
Stack<int, std::vector> s;

现在,这仅允许具有两个模板参数的容器作为基础类型,因此您最好采用标准的做法:将其视为普通类型:

template <typename T, typename ContainerType>
class Stack{
  ContainerType container;
  // ...
};

// usage:
Stack<int, std::vector<int> > s;

确保底层类型具有相同的T,你可以做一个假的“静态断言”,或者如果你有一个启用了 C++0x 的编译器,你可以做一个实际的静态断言:

#include <tr1/type_traits> // C++03 us std::tr1::is_same
//#include <type_traits> // C++0x, use std::is_same

template <typename T, typename ContainerType>
class Stack{
  typedef typename ContainerType::value_type underlying_value_type;
  typedef char ERROR_different_value_type[
               std::tr1::is_same<T, underlying_value_type>::value ? 1 : -1
                                         ]
  ContainerType container;
  // ...
};

这是有效的,因为如果T与使用过的容器不同T,这将是一个typedef char ERROR_different_vale_type[-1],并且负大小的数组不可能存在,这会导致编译器错误。 :) 现在,使用 C++0x 你可以static_assert that:

#include <tr1/type_traits> // C++03
//#include <type_traits> // C++0x

template <typename T, typename ContainerType>
class Stack{
  typedef typename ContainerType::value_type underlying_value_type;
  static_assert(std::tr1::is_same<T, underlying_value_type>::value,
    "Error: The type of the stack must be the same as the type of the container");
  ContainerType container;
  // ...
};

为了方便起见,您现在可以为常见情况指定默认模板参数:

template <typename T, typename ContainerType = std::vector<T>>
class Stack{
  ContainerType container;
  // ...
};

// usage:
Stack<int> s;

此时你可以使用std::stack它正是这样做的(尽管它使用std::deque作为基础类型)。 :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 模板 template (双模板?) 的相关文章

随机推荐

  • 为属性设置默认值

    是否可以在没有属性主体的情况下设置默认值 最好有注释 SetTheDefaultValueTo true public bool IsTrue get set SetTheDefaultValueTo false public bool I
  • Swift3 sqlite3_open() 打开现有文件

    let file url try FileManager default url for documentDirectory in userDomainMask appropriateFor nil create false appendi
  • 数据帧的频率

    我有一个用日期索引的数据框 Python 日期时间对象 如何找到数据框中数据的月数频率 我尝试了属性data frame index freq 但它返回无值 我也尝试过asfreq函数使用data frame asfreq M how st
  • 防止 Emacs 滚动到缓冲区末尾

    当我用鼠标或滚动条滚动到缓冲区末尾时 是否可以添加任何内容到 emacs 文件中 以防止 emacs 添加新行 我已经有了 setq next line add newlines nil 但这似乎只适用于我用键盘移动时 我对此主题进行了多次
  • 如何通过单击图标更改 font-awesome 图标的颜色

    var garbage document getElementById garbage garbage addEventListener click function garbage style color 66c144 div i cla
  • 使用 ping 伪随机选择的 IP 地址可以生成真正的随机数吗?

    提出的问题是在第二年的计算机科学讲座中提出的 当时讨论了在确定性计算设备中生成数字的不可能性 这是唯一不依赖于非商品级硬件的建议 随后 没有人愿意拿自己的声誉来明确支持或反对它 任何人都愿意表达支持或反对的立场 如果是这样 是否提及可能的实
  • 推力结构向量的迭代器

    我正在尝试以这种方式访问 向量元素 struct point unsigned int x unsigned int y thrust device vector
  • C# - 让所有派生类调用基类构造函数

    我有一个基类角色 它有几个派生自它的类 基类有各种字段和方法 我的所有派生类都使用相同的基类构造函数 但如果我不在派生类中重新定义构造函数 则会收到错误 错误 类 子类 不包含采用此数量参数的构造函数 我不想在每个派生类中重新定义构造函数
  • emacs 全局放大/缩小

    我知道我可以使用 C x C 放大 缩小 但这仅适用于当前文件 一旦我打开另一个 文本又回到默认值 一遍又一遍地这样做真的很烦人 如何保持当前 emacs 会话的全局缩放级别 我知道如果您知道确切的字体大小 则可以在初始化文件中设置它 但我
  • 使用 Instrumentation 记录未处理的异常

    我试图使用仪器来调试java应用程序 当前系统存在的问题是 几乎没有写任何日志语句 不良的异常处理 这使得追踪功能损坏的根本原因变得非常困难 为了处理这种情况我开发了工具 java代理使用InstrumentationAPI 我能够注入日志
  • 如何对面板进行双缓冲?

    我有一个带有轮盘赌轮的面板 我需要对面板进行双缓冲 以使其停止闪烁 谁能帮我吗 EDIT 是的 我已经尝试过了 panel1 doublebuffered不存在 只有this doublebuffered 我不需要缓冲表单 只需缓冲面板 另
  • C# 如何将 Resharper 错误视为 msvs 2010 中的编译错误?

    我想将 resharper 5 0 错误 可能的空引用异常 视为 MSVC 2010 编译错误 是否可以 Update 因为人们似乎仍在寻找这个答案 这 或者非常类似的事情 今天是可能的 例如StyleCop 分析仪 https githu
  • 以 O(深度) 填充树的函数

    纯函数式数据结构 http books google com books about Purely Functional Data Structures html id SxPzSTcTalAC有以下练习 2 5 Sharing can b
  • Angular2动态改变CSS属性

    我们正在制作一个Angular2应用程序我们希望能够以某种方式创建一个全局 CSS 变量 并在分配变量时更新属性值 我们已经使用 Polymer 一段时间了 现在我们正在切换到 Angular2 组件 并且我们使用了 CSS 属性 Poly
  • 等待异步脚本结果超时 Selenium C# Protractor

    我正在尝试使用 Protractor net 为 AngularJS 平台创建一个自动化测试脚本 并在 C 中使用 Selenium 我使用下面的代码创建了驱动程序 driver new FirefoxDriver Ngdriver new
  • Windows 无法绑定到 49690 以上的端口

    我运行一个绑定到端口 50005 的应用程序已经有一段时间了 似乎最近发生了一些变化 我的机器上没有应用程序能够绑定到 127 0 0 1 上 49690 以上的任何 TCP 端口 有谁知道什么时候 发生了什么变化 操作系统名称 Micro
  • Resharper - 说服管理层[重复]

    这个问题在这里已经有答案了 可能的重复 Reshaper 的业务案例 https stackoverflow com questions 2298308 business case for resharper 我刚刚毕业 正在为我的第一家公
  • 如何知道 MPMoviePlayerController 正在 Iphone OS 3.0 中播放

    我需要知道 MPMoviePlayerController 是否在特定时刻正在播放 在 iphone 3 0 中 它不会触发 MPMoviePlayerContentPreloadDidFinishNotification 有谁知道有什么解
  • IIS 自动启动未禁用空闲超时

    我在 Windows Azure Web 角色上设置 ASP NET 自动启动 我在 Windows Server 2012 上使用 ASP NET 4 5 和 IIS 8 我基本上是跟着那些指示 http www iis net lear
  • C++ 模板 template (双模板?)

    我想建立一个Stack类 因此用户将能够选择他想要使用哪个容器来实现Stack 例如 List Vector 部分代码 stack h ifndef STACK H define STACK H template