`
qqsunkist
  • 浏览: 32996 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论
阅读更多

模板使用技巧基础

这篇文章主要记下实际工程中使用模板的一些基本技巧,其中主要包括typename关键字的使用,定义模板成员函数,定义嵌套类模板,双重模板类型参数(template template parameter),以及零值初始化的技巧。

 

一、关键字typename

关键字typename是C++标准化过程中被引入的,目的是告诉编译器模板类型参数或者其内的某个标识符是个类型。

template <typename T>
class MyClass{
public:
   typename T::subtype *ptr;
   ... ...
};

 第二个typename关键字说明subtype是T内部定义的一个类型,所以ptr是一个指向subtype的指针。如果移除掉typename关键字修饰,那么subtype会被编译器误认为是T内部的一个静态成员,所以 T::subtype * ptr 就变成了一个表达式。

 

通常如果某个与模板参数相关的名称是个类型时,前面就需要添加关键字typename.

二、.template构件

在引入typename之后,又出现了一个类似问题。如下面的代码所示

template<int N> 
void printBitset (std::bitset<N> const& bs) 
{ 
    std::cout << bs.template to_string<char,char_traits<char>, 
                                       allocator<char> >(); 
} 

 .template构件显得比较古怪,如果没有它,编译器不会认为紧跟其后的‘<’ 是模板参数列表的开始,而非一个小于号。

 

小结:.template构件只有在其前的构件(本例是bs)依赖于模板类型参数时,才会被使用。

 

三、使用this->

template <typename T> 
class Base { 
  public: 
    void exit(); 
};

template <typename T> 
class Derived : Base<T> { 
  public: 
    void foo() { 
        exit();   // calls external exit() or error 
    } 
}; 

 如果class templates拥有base classes,那么其出现的成员名称'exit()'并非总是等价于‘this->exit()',即base<T>::exit()。应在调用前,显式添加’this->' 或‘base<T>::'才可通过编译。

 

使用建议准则:任何使用基类继承而来的成员或成员函数,如果基类与模板类型参数相关,那么最好在使用前加上'this->'或者’base<T>::'的修饰。

 

四、成员模板

成员模板可以是嵌套模板类也可以是成员函数模板。

// basics/stack6decl.hpp 

template <typename T, typename CONT = std::deque<T> > 
class Stack { 
  private: 
    CONT 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 T, typename CONT2> 
    Stack<T,CONT>& operator= (Stack<T,CONT2> const&); 
}; 


// basics/stack6assign.hpp 

template <typename T, typename CONT> 
 template <typename T, typename CONT2> 
Stack<T,CONT>& 
Stack<T,CONT>::operator= (Stack<T,CONT2> const& op2) 
{ 
    if ((void*)this == (void*)&op2) {    // assignment to itself? 
        return *this; 
    } 

    Stack<T> 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; 
}

 通过上述成员赋值模板函数,就可完成以deque实现的stack赋值到以vector实现的stack,不过stack中保存的元素类型仍然相同。

 

五、双重模板类型参数(Template Template Parameter)

template <typename T, typename CONT = std::deque<T> > 
class Stack { 
...
};

如此声明,在使用不同container作为stack的实现时,需要再次重复指定元素类型。如果使用ttp的话,那么就可以不需要重复指定元素类型了。那么ttp到底是个什么东东呢?实际上ttp就是在声明时告诉编译器模板类型参数本身也是一个模板类。按照ttp原则,这个例子中,stack的container模板类型参数本身也是一个类模板。所以修改如下

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

如果按照ttp声明stack模板类时,那么在使用不同container作为stack的实现时,就不再需要重复指定元素类型了。

 

技巧1:因为TTP中的模板类型参数(ELEM)并没有被使用,所以形式上可以忽略。所以下面的这个声明也可以

template<
                typename T, 
                template<typename>class CONT=std::deque 
              >
class Stack { 
... ...
};
 

注意事项:

      成员函数模板的声明及实现中的模板类型参数也需要按照TTP原则做出相同的改动。

模板模板参数的匹配(Template Template Argument Matching)

如果试图使用按照TTP原则修改后的class templates stack,编译器会报错说std::deque不符合template template parameter CONT的要求,原因是TTP原则不仅要求template parameter本身是个class template,而且这个class template的参数必须严格匹配它所替换的TTP的参数。

 

再次考虑本例,原本代表container的那个template parameter是 std::deque<T, alloc<T> >, 很显然这个container是需要两个template parameter的,但是当我们之前用以替换的class template却只声明了一个template parameter,这就导致了参数匹配不成功。所以需要进一步修改一下class template Stack的声明如下

 

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

 PS: 似乎为了少写一个T, 却使class template声明变得很复杂。

六、零值初始化

template <typename T> 
void foo() 
{ 
    T x = T();      // x has undefined value if T is built-in type 
} 

假定T并无默认构造函数时,x的初值就无法被正确初始化,进而引发未定义的行为。因此在定义class template时,一定要定义默认构造函数,初始化其内部成员。当然,如果T本身是内建类型时,如int, bool等, 当默认构造函数被调用后,其值就会被初始化为0。

 

小结:

 1. 当要操作一个取决于template parameter的类型名称时,应该在前面加typename关键字修饰。

 2. 嵌套类和成员函数也可以是模板。

 3. 赋值运算符的template版本并不取代默认赋值运算符。

 4. 把class template作为template parameter使用的技巧成为Template Template Parameter。

 5. Template Template Arguments必须完全匹配其对应参数。

 6. 当具现化一个内建类型的变量时,如果需要设定初值,必须明确调用其默认构造函数。

 

 

分享到:
评论

相关推荐

    C++ Templates 中英文两版

    这本书深入探讨了C++模板的各个方面,包括基本概念、模板元编程、模板特化、模板技巧以及如何有效地使用和调试模板代码。对于希望深入理解C++模板机制的开发者来说,这是一份宝贵的资源。 2. **C++ Templates 简体...

    C++ Templates(简体中文版)(带完整书签的pdf)

    《C++ Templates(简体中文版)》是一本专注于C++模板编程的指南书籍,它不仅为读者提供了模板的基本概念,还涵盖了常用技巧和应用实例,帮助读者构建坚实的C++模板知识基础。C++模板是该语言强大功能的体现,允许...

    C++ Templates 英文版

    根据提供的信息,我们可以总结出以下关于《C++ Templates: The Complete Guide》这本书的关键知识点: ### 书籍基本信息 - **书名**:C++ Templates: The Complete Guide - **作者**:David Vandevoorde 和 ...

    C++ Templates 第2版 英文版

    1. **模板基础**:包括模板的声明、实例化以及如何使用模板参数推断。 2. **模板特化与偏特化**:当通用模板不能满足特定需求时,可以通过特化或偏特化来提供更精确的实现。 3. **模板元编程**:使用模板作为编译时...

    Django10个使用技巧

    例如,定义`TEMPLATE_DIRS`时,可以使用`BASE_DIR + '/templates'`。 2. **利用{% url %}模板标签**:在模板中使用{% url %}替代硬编码的URL,这样当项目结构发生变化时,链接依然可用。通过将视图函数与URL模式...

    C++ templates 模板

    通过系统地学习《C++ Templates-The Complete Guide》,读者不仅可以获得扎实的理论基础,还能掌握实用的编程技巧,为开发高质量的C++软件打下坚实的基础。无论是对于初学者还是有经验的开发者来说,这本书都是不可...

    C+++Templates简体中文版 高清可复制版

    在阅读本书之前,建议读者已经具备一定的C++基础知识,包括类、继承等面向对象编程概念,以及标准库的使用。对于C++标准,本书主要依据1998年的标准,并考虑了2002年技术勘误的内容。如果读者在C++基础方面有所欠缺...

    C++ Templates - The Complete Guide

    《C++ Templates - The Complete Guide》这本书旨在向软件架构师和工程师们清晰地展示如何正确地使用C++模板,以构建和维护更清洁、更快、更智能的软件。 首先,书中通过一个富有洞察力的教程介绍了C++模板的基础...

    C++ Templates(侯捷版1-10章).pdf

    - **第一部分(第2~7章)**:介绍了模板的基本概念,包括模板类和模板函数的定义、使用方法、语法特点等基础知识。 - **第二部分(第8~13章)**:详细讲解了模板的语言细节,如模板参数、模板特化、模板元编程等高级...

    c++ templates 全览(侯捷)

    - **表达式模板(Expression Templates)**:一种优化技巧,用于提高模板类的性能。 - **元编程(Template Metaprogramming)**:使用模板在编译时执行计算。 - **类型函数(Type Functions)**:通过模板实现的函数,...

    C++ Templates中文版 范德沃德 (David Vandevoorde)、 约祖蒂斯 (Nicolai M.Josuttis) 满减

    《C++ Templates中文版》是C++模板编程的完全指南,旨在通过基本概念、常用技巧和应用实例三方面的有用资料,为读者打下C++模板知识的坚实基础。书中详细讲解C++模板语言的概念,使用C++模板的常用设计技巧,还运用...

    C++ Templates 中文版 陈伟柱

    10. **模板的编译期开销与技巧**:虽然模板提供了强大的功能,但过度使用可能导致编译时间增加和代码膨胀。合理地使用模板,如限制模板深度、避免模板模板参数等,可以减轻这些问题。 配合书本配套的源码,读者可以...

    C++Templates(高清pdf扫描版)

    本书是C++模板编程的完全指南,旨在通过基本概念、常用技巧和应用实例3方面的有用资料,为读者打下C++模板知识的坚实基础。 全书共22章。第1章全面介绍了本书的内容结构和相关情况。第1部分(第2~7章)以教程的风格...

    中文版:《C++Templates全览》 侯捷荣耀姜宏 译

    总之,《C++ Templates全览》是一本深度解析C++模板技术的权威之作,适合有一定C++基础并希望深入学习模板的开发者阅读。通过这本书,读者不仅可以掌握模板的基本用法,还能了解到模板背后的原理和高级技巧,从而在...

    C++ Templates 中文版

    本书是一本对基本概念和语言特性...·从基础的到早前没有文字约定的惯用语法和技巧; ·如何在不对性能和安全性造成损害的前提下进行源代码重用; ·如何提高C++程序的效率; ·如何构建更具灵活性和可维护性的软件。

    C++ Templates(简体中文版).rar

    书中首先介绍了模板的基础知识,包括函数模板和类模板的声明与使用,如何通过模板参数推导简化编程,以及模板特化来处理特定类型的情况。此外,作者还深入讨论了模板元编程,这是一种利用模板进行编译时计算的技术,...

Global site tag (gtag.js) - Google Analytics