• c++11——模板的细节改进


       c++11改进了编译器的解析规则,尽可能的将多个右尖括号(>)解析为模板参数结束符,方便编写模板相关的代码。

    1. 模板的右尖括号

        之前的c++标准中,模板套模板中右尖括号不能连在一块,否则会和右移操作符混淆,如 vector< map< int, int> > //右边的两个>要分开。 
    而在c++11中,这种限制取消了,编译器能够判断出">>"是右移操作符还是模板参数的结束标记。

    2. 模板的别名

        之前的c++使用 typedef 来为类型指定别名,在c++11中,可以使用using 来指定别名。

        typedef std::map< std::string, int> map_int_t;
        //using map_int_t = std::map<std::string, int>;
        typedef std::map< std::string, std::string> map_str_t;
        //using map_str_t = std::map< std::string, std::string>;
        如果需要指定map的key为std::string, 而value任意,则对于之前的c++,不得不这么做:
        template<typename T>
        struct str_map{
        typedef std::map< std::string, T> type;
        };
        //....
        str_map<int>::type impl;
        //在c++11中,使用using进行简化
        template<typename T>
        using str_map_t = std::map< std::string, T>; //指定类型别名
        ....
        str_map_t<int> map_int_t; //用类型别名定义变量
    
        使用typedef
        typedef void(*func_t)(int, int);
        使用using
        using func_t = void(*)(int, int);
        待模板参数的函数指针
        使用typedef
        template<typename T>
        struct func_t{
        typedef void(*type)(T, T);
        };
        func_t<int>::type xx_1;
        使用 using
        template<typename T>
        using func_t = void(*)(T, T);
        func_t xx_2; //声明变量
    
    3. 函数模板的默认参数

        在c++98/03中,类模板可以有默认参数,如下:

        template<typename T, typename U = int, U N = 0>
        struct Foo{
        ....
        };
    

    但是不支持函数的默认模板参数

        template< typename T = int> //在c++98/03中不被支持
        void func(void){
        ....
        };
    

        在c++11中,可以支持函数模板的默认参数

    template< typename T = int> //在c++98/03中不被支持
    void func(void){
    ....
    };
    int main(){
        func(); //使用了默认模板参数 int
        return 0;
    }
    

        当所有模板参数都有默认参数时,函数模板的 调用如同一个普通函数。对于类模板而言,即使所有参数都有默认参数,在使用时也必须在模板名后面跟随<>来实例化。 
        函数模板的默认参数在使用规则上也和其他的默认参数有所区别,例如,没有必须写在参数表最后的位置。同时,没有默认值或者类型的参数,可以自动推导

    template<typename R = int, typename U> //默认模板参数没有必须写在参数表最后的位置
    R func(U val){
        return val;
    }
    
    int main(void){
        func(123);  //参数U使用自动推导,推导为int
        return 0;
    }
    

    在调用函数模板时,若显示指定模板的参数,参数填充顺序从右往左!!

    func<long> (123); //参数从右向左填充,则U被视为long类型,则返回的123为long类型
    

      
      
     

    函数模板参数类型自动推导

        在C++语言中实现了这一自动推导模板参数值的功能。凡是可以推导出的模板参数“值”,就无需在模板实参列表中写明。 
        另外,当默认模板参数和模板参数自动推导同时使用时,若函数模板无法自动推导出参数类型,则编译器将使用默认模板参数,否则将使用自动推导出的参数类型。即自动推导类型优先。

    template<typename T>
    void f(T val){
        cout << val << endl;
    }
    tempalte<typename T>
    struct identity{
        typedef T type;
    };
    template<typename T = int>
    void func(typename identity<T>::type val, T = 0){
    ..
    };
    int main(){
        f("hello world"); //模板参数自动推导,T 为 const char*
        func(123);        //T 为int
        func(12,12.0);    //T 为 double,因为func中的第二个参数为12.0,这样参数模板T就被优先自动推导为double
        return 0;
    }
    
  • 相关阅读:
    java_泛型
    java工具类Collections
    Map集合的遍历
    集合元素顺序的实现
    apk比较版本大小
    存储过程与SQL语句怎么选择
    线程协作-生产者/消费者问题
    线程中断、线程让步、线程睡眠、线程合并
    如何将字符串去重复demo工具
    JavaScript 中的函数介绍
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4802751.html
Copyright © 2020-2023  润新知