c++ template归纳学习5

简介:

双重模板参数:

我们还是以前几篇中的Stack为例子i:代码如下:

template <typename T, 
          template <typename ELEM> class CONT = std::deque > 
class Stack { 
  private: 
    CONT<T> elems;         // elements 

  public: 
    void push(T const&);   // push element 
    void pop();            // pop element 
    T top() const;         // return top element 
    bool empty() const {   // return whether the stack is empty 
        return elems.empty(); 
    } 
}; 
在这段代码中,我们的第二个模板参数修改为:template <typename ELEM> class CONT

和往常一样,你可以使用class替代typename,但是CONT必须是class。

template <typename T, 
          template <class ELEM> class CONT = std::deque>  // OK 
class Stack { 
  … 
}; 
but the following is not:

template <typename T, 
          template <typename ELEM> typename CONT = std::deque> 
class Stack {                                             // ERROR 
  … 
};

由于上面例子中的ELEM实际中没有用到,其实是可以省略的。

我们实现一个成员函数看看:

template <typename T, template <typename> class CONT> 
void Stack<T,CONT>::push (T const& elem) 
{ 
    elems.push_back(elem);    // append copy of passed elem 
} 

但是如果试图使用上面的stack,编译器会说deque不符合CONT的要求,问题在于,std中的deque要求不只是一个参数,第二个参数是一个配置器,他虽然有预设值,但是当它被用来匹配CONT参数的时候,预设值被编译器忽略了。

对于这个问题,我们可以修改,使得CONT参数要求一个带两个参数的容器。

template <typename T, 
          template <typename ELEM, 
                    typename ALLOC = std::allocator<ELEM> > 
                    class CONT = std::deque> 
class Stack { 
  private: 
    CONT<T> elems;         // elements 
    … 
}; 
最终版本如下:

// basics/stack8.hpp 

#ifndef STACK_HPP 
#define STACK_HPP 

#include <deque> 
#include <stdexcept> 
#include <allocator> 

template <typename T, 
          template <typename ELEM, 
                    typename = std::allocator<ELEM> > 
                    class CONT = std::deque> 
class Stack { 
  private: 
    CONT<T> elems;        // elements 

  public: 
    void push(T const&);  // push element 
    void pop();            // pop element 
    T top() const;         // return top element 
    bool empty() const {   // return whether the stack is empty 
        return elems.empty(); 
    } 

    // assign stack of elements of type T2 
    template<typename T2, 
             template<typename ELEM2, 
                      typename = std::allocator<ELEM2> 
                      >class CONT2> 
    Stack<T,CONT>& operator= (Stack<T2,CONT2> const&); 
}; 

template <typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::push (T const& elem) 
{ 
    elems.push_back(elem);    // append copy of passed elem 
} 

template<typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::pop () 
{ 
    if (elems.empty()) { 
        throw std::out_of_range("Stack<>::pop(): empty stack"); 
    } 
    elems.pop_back();         // remove last element 
} 

template <typename T, template <typename,typename> class CONT> 
T Stack<T,CONT>::top () const 
{ 
    if (elems.empty()) { 
        throw std::out_of_range("Stack<>::top(): empty stack"); 
    } 
    return elems.back();      // return copy of last element 
} 
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) 
{ 
    if ((void*)this == (void*)&op2) {    // assignment to itself? 
        return *this; 
    } 

    Stack<T2> tmp(op2);              // create a copy of the assigned stack 

    elems.clear();                   // remove existing elements 
    while (!tmp.empty()) {           // copy all elements 
        elems.push_front(tmp.top()); 
        tmp.pop(); 
    } 
    return *this; 
} 

#endif // STACK_HPP 
测试如下:

// basics/stack8test.cpp 

#include <iostream> 
#include <string> 
#include <cstdlib> 
#include <vector> 
#include "stack8.hpp" 

int main() 
{ 
    try { 
        Stack<int> intStack;        // stack of ints 
        Stack<float> floatStack;    // stack of floats 

        // manipulate int stack 
        intStack.push(42); 
        intStack.push(7); 

        // manipulate float stack 
        floatStack.push(7.7); 

        // assign stacks of different type 
        floatStack = intStack; 

        // print float stack 
        std::cout << floatStack.top() << std::endl; 
        floatStack.pop(); 
        std::cout << floatStack.top() << std::endl; 
        floatStack.pop(); 
        std::cout << floatStack.top() << std::endl; 
        floatStack.pop(); 
    } 
    catch (std::exception const& ex) { 
        std::cerr << "Exception: " << ex.what() << std::endl; 
    } 

    // stack for ints using a vector as an internal container 
    Stack<int,std::vector> vStack; 
    … 
    vStack.push(42); 
    vStack.push(7); 
    std::cout << vStack.top() << std::endl; 
    vStack.pop(); 
} 
程序的输出为:

7 42 Exception: Stack<>::top(): empty stack 7


==============================================================================
本文转自被遗忘的博客园博客,原文链接:http://www.cnblogs.com/rollenholt/archive/2012/03/08/2384921.html,如需转载请自行联系原作者
相关文章
|
3月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
81 0
|
26天前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
|
1月前
|
Java 编译器 C++
c++学习,和友元函数
本文讨论了C++中的友元函数、继承规则、运算符重载以及内存管理的重要性,并提到了指针在C++中的强大功能和使用时需要注意的问题。
21 1
|
4月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
4月前
|
人工智能 分布式计算 Java
【C++入门 一 】学习C++背景、开启C++奇妙之旅
【C++入门 一 】学习C++背景、开启C++奇妙之旅
|
4月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
4月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
4月前
|
存储 C++ 索引
|
4月前
|
存储 C++ 容器
|
4月前
|
算法 数据处理 C++