模板专业化

时间:2014-10-07 19:21:34

标签: c++ templates

我正在阅读Addison Wesley的“C ++模板:完整指南”一书,并对类模板的特化提出了疑问。我理解它是如何工作的,但是我很难理解你何时会使用给定示例中的这个功能。以下是Stack类的一般定义:

#include <vector> 
#include <stdexcept> 

template <typename T> 
class Stack { 
  private: 
    std::vector<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(); 
    } 
}; 

这是专业化

#include <deque> 
#include <string> 
#include <stdexcept> 
#include "stack1.hpp" 

template<> 
class Stack<std::string> { 
  private: 
    std::deque<std::string> elems;  // elements 

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

我的问题在于它似乎打破了关于封装的OOP原则。客户端是否需要知道有两个定义,可能在不同的头文件中,然后根据给予Stack类的类型T知道要包含哪个定义?在我看来,你最好在这个场景中实现两个不同的类,一个通用的Stack类和一个专门的StackString类。

思想?

2 个答案:

答案 0 :(得分:1)

  

客户是否需要知道有两个定义,可能是   到不同的头文件,然后知道要包含哪一个   给予Stack类的类型T?

绝对不需要将它们放入两个不同的 open 标头中,即图书馆用户将看到并使用的标头。它们可能在内部组织在两个不同的实现头中,然后包含在用户将看到和包含的主要头中。但是用户既不知道 是显式特化,也不知道他使用

// Stack.impl.hpp

// primary template:
template <typename T>
class Stack {
   // [...]
};

// Stack_StringSpec.impl.hpp

#include "Stack.impl.hpp"
// explicit specialization:
template <>
class Stack<std::string> {
   // [...]
};

// Stack.hpp

#include "Stack.impl.hpp" // Included for clarity
#include "Stack_StringSpec.impl.hpp"

请注意,在大多数情况下,仍然会记录专业化,因为它肯定存在,原因是用户应该/需要注意。 (以std::vector<bool>为例。)

答案 1 :(得分:0)

一个专门的类只与非特定的变体共享基本名称,实际上你必须完全重写接口和实现,不能重用以前的代码。

最受欢迎的专业是std::vector<bool>bool类型需要1个字节,但实际上一个字节可以存储8个bool。当你需要一个bool数组时,在单个字节中包含更多的bool似乎是合理的,以减少内存消耗。这里的专业化可以实现这一点。

对于用户来说,一切都是透明的:你完全使用vector<bool>作为vector<int>,但是第二个依赖于动态的整数数组,第一个以完全不同的方式使用位。

专业化不一定必须在同一个标​​题中,但是当用户包含类时,应该注意使所有专业化都可见,否则他可能无法使用它们(你不想记得在使用vector<bool>时包含其他文件。