`
qqsunkist
  • 浏览: 32591 次
  • 性别: 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 第2版 英文版

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

    Django10个使用技巧

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

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

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

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

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

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

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

    C++ Templates 中文版 陈伟柱

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

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

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

    C++ Templates 中文版

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

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

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

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

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

    C++.Templates.The.Complete.Guide.2nd.Edition.epub

    书中详细介绍了模板元编程的基本概念、技巧和最佳实践,包括类型别名模板、类型转换、类型列表和类型属性查询等。 4. **模板特化**:模板特化允许为特定的数据类型提供定制的实现。这在某些情况下是必要的,比如...

    Addison.Wesley.C++.Templates-The.Complete.Guide.rar

    书中有专门的章节讲解完全特化和部分特化的使用场景和技巧。 4. 模板元编程:模板元编程是一种在编译时执行计算的技术,利用模板和类型系统进行编程。这一部分将涵盖模板元编程的基本原理和应用,如类型枚举、类型...

    c++ templates the complete guide.rar

    《C++ Templates: The Complete Guide》是一本深入探讨C++模板技术的专业书籍,由David Vandevoorde和 Nicolai M. Josuttis 联合撰写。这本书是C++程序员学习模板的权威指南,尤其适合那些希望提升对模板理解深度的...

    C++ Templates - The Complete Guide英文版.rar

    通过阅读《C++ Templates - The Complete Guide》英文版,读者将能够掌握C++模板的各个方面,提升编程技巧,更好地利用这一强大的语言特性来设计高效、灵活的软件系统。无论是开发库、编写复杂算法还是优化代码,...

    [pdf]C++ templates(En) and Modern C++ Design(En and Chn)

    《C++ Templates: The Complete Guide》可以帮助初学者建立起模板编程的基础,而《Modern C++ Design》则引导读者探索更高级和创新的编程技巧,提升代码质量和效率。通过学习这两本书,开发者可以更好地利用C++的...

    300多套网站模板源码。 Web-templates

    标题 "300多套网站模板源码" 暗示了这是一个包含多种...通过深入探索这个"Web-templates-master"压缩包,无论是初学者还是经验丰富的开发者,都能从中学习到实际的网页开发技巧和设计趋势,提升自己的网站构建能力。

    templates-源码.rar

    4. **模板元编程**:这是一种利用模板作为编程工具的高级技巧,可以在编译期进行计算,生成定制化的代码。这在需要高效且对性能敏感的场合十分有效。 5. **SFINAE原则**:Substitution Failure Is Not An Error,这...

Global site tag (gtag.js) - Google Analytics