zoukankan      html  css  js  c++  java
  • C++模板元编程(三)

    C++模板元编程(三)

    typename和template关键字

      正确的使用关键字typename与template可以很多细微的语法错误,总结如下。

      1. template关键字用来引入模板声明和定义,如:

    template <class T> class Vector;

      2. typename关键字通常用来取代class来声明模板类型的参数,如:

    template <typename T> class Vector;

      3. typename关键字和class关键字在声明模板类型参数时,一般情况下等价(区别见后面)。但有时选用其中某个关键字,在概念上更加明确,如:

    // 模板参数中,第一个是声明一个type参数,第二个是一个类型为T::value_type的值。
    // 可见第二种方式,概念更明确,虽然两种模板声明都可以。 
    template<typneame T, typename T::value_type> class Test;
    template<class T, typename T::value_type> class Test;

      4. 当一个依赖名表示的是一个依赖性的类型时,需要使用typename关键字(对非依赖名,是否使用typename关键字对其进行限定完全是可选的),如:

    template<typename Tp>
    class IteratorTraits
    {
        public:
            // 当使用一个依赖性的类型,且该名字表示一个类型时,C++标准要求使用typename关键字表明该依赖名是一个类型
            typedef typename Tp::value_type value_type;
            typedef typename Tp::reference reference;
            typedef typename Tp::pointer pointer;
            typedef typename Tp::difference_type difference_type;
            typedef typename Tp::iterator_category iterator_category;
    };
    
    template<typename T>
    class Test
    {
        public:
            typename std::vector<T> v; // typename是可选的
        //  typedef typename int value_type; //(错误) typename不能用在非限定性(也就是不带::前缀)上
    };
    
    // typedef typename int value; // (错误)typename不能使用在模板之外的任何场合
    
    // typename不能用于基类的名字上,即便它是依赖性的也不行
    template<class T> struct Base;
    
    template<class T> struct Derived 
        : typename Base<T>::type // (错误)
    {};
    
    // typename不能用于友元声明中
    template<class T> class Test
    {
        friend class typename T::type;
    };

      5. 当一个依赖名是成员模板时,需要使用template消除歧义,如:

    template<class T>
    int f(T& x)
    {
        // x.convert成员函数模板,需要使用template关键字。不然的话可能会将convert当做数据成员,
        // 而解析为(x.convert < 3) > pi, 从而造成歧义
        return x.template convert<3>(Pi)
    }
    
    // 注:template禁止用在模板之外的任何场合,包括显示(完全)模板特化。也不能出现在using声明中

    注意事项

    1. 模板函数中,参数类型不允许自动类型转换。

    2. 当存在同名的模板函数和非模板函数时,优先调用模板函数。但可以使用空的模板参数列表的形式,从template具现体中挑选适当的对象。

    3. 确保所有形式的重载函数都写在它们的调用点之前。

    4. 以模板类template <typename T> Test{...}申明变量和函数时都应该写成Test,然而只需要class名称而不需要class类型时,
      只需写Test即可。如构造函数、析构函数的什么就属于这种情况。

    5. 在模板类中的模板成员函数,只有被实际调用到了,才会被实例化。

    6. 模板的特化需以template<>开头。

    7. 在模板类的模板参数中,可以指定模板参数的默认值template<typename T, typename U=int>

    8. 模板类的模板参数可以指定为非类型模板参数,同时也可以指定非类型函数模板参数。

    9. 模板的非类型参数只能是整型、enum、外部链接的指针,而不能是浮点类型、类类型对象与内部链接的指针。(在g++ 4.9.1上测试过)

    10. 模板也可以作为模板参数。

    11. 模板的声明与定义要放在同一个文件中。(也可以不放在同一个文件中,使用显示实例化)

    12. 显示实例化,以template打头,模板参数被完全替代。

    13. 成员函数模板不能声明成virtual。

    14. 在同一作用域空间内,类模板不能和其它不同类型的实体共用同一个名称,而非模板类则可以和其它不同实体有相同的名称。

    15. 模板函数不能使用C链接方式(export “C”)。

    16. 模板通常使用外部链接,唯一例外的是static namespace scope 函数模板。

    17. 双重模板参数的声明不能使用struct和union,只能使用class。
      template<template<typename T> class C> ...

    18. 模板的实例化(instantiation)是由泛化的模板定义式产生出实际函数和类型的过程。

    19. Generic Programming, Traits, Policy classes, meta-programming, Expression Template。

    20. Trait表现为一个template parameter的自然附加属性。 Policies表现泛化函数和类型间的可设置行为。

    参考资料

    1. 《C++模板元编程》(David Abrahams, Aleksey Gurtovoy )
    2. 《C++ 模板全览》丁志强译
  • 相关阅读:
    http4j
    EmbeddedBrowser
    curl v www.linode.com查看请求及响应信息
    JRUN
    PAC Manager: Ubuntu 上强大的 SSH 帐号管理工具,可取代 SecureCRT
    centos下载地址
    Web应用调试:现在是Weinre和JSConsole,最终会是WebKit的远程调试协议
    用ClusterSSH管理多台Linux服务器(2)
    Ubuntu + IntelliJ + Maven + Jetty + JRebel
    Java的连接池程序
  • 原文地址:https://www.cnblogs.com/corfox/p/5414992.html
Copyright © 2011-2022 走看看