• 学习C++第二十五课--using定义模板别名与显式指定模板参数笔记


    一、using定义模板别名

    typedef一般用来定义类型别名,如

    typedef unsigend int uint_t;

    这里我们先演示一下map容器的简单应用,程序如下:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int main()
    6. {
    7. mapint> mymap;//定义一个map类型的mymap容器
    8. mapint>::iterator it;//迭代器
    9. mymap.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
    10. mymap.insert({ "helloworld",2 });
    11. mymap.insert({ "abcdefghij",3 });
    12. for(it=mymap.begin();it!= mymap.end();it++)//轮询输出容器里面的string字符串和int数据
    13. {
    14. cout << it->first;
    15. cout << " ";
    16. cout << it->second;
    17. cout << endl;
    18. }
    19. return 0;
    20. }

    如果在实际开发有这样一个需求:希望定义一个类型,但这个类型不固定,例如对于map类型容器中的元素,元素的键(key)固定是std::string类型,但是值(value)不希望固定为int或者固定为string类型,希望可以自己自由指定。

    这个需求通过typedef不好做到,因为typedef一般都是用来给固定类型起别名,二这里的类型名不固定,像一个模板一样。在C++98标准中,开发者通过一个变通的办法来达到这个目的,通过一个类模板来实现,在.cpp文件中这样写:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. template<typename wt>
    6. class map_struct
    7. {
    8. public:
    9. typedef map type;//或typedef std::map type;
    10. };
    11. int main()
    12. {
    13. map_struct<int>::type mymap;
    14. mapint>::iterator it;//迭代器
    15. mymap.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
    16. mymap.insert({ "helloworld",2 });
    17. mymap.insert({ "abcdefghij",3 });
    18. for (it = mymap.begin(); it != mymap.end(); it++)//轮询输出容器里面的string字符串和int数据
    19. {
    20. cout << it->first;
    21. cout << " ";
    22. cout << it->second;
    23. cout << endl;
    24. }
    25. return 0;
    26. }

    可以看到,为了实现这种比较通用的以string类型为key,以任意类型为value的map容器,不得不写一个类模板来达到此目的。

    在C++11的新标准使类似的问题解决起来变得非常简单,不用定义类模板了,如下两行代码就解决问题:

    1. template<typename T>
    2. using str_map_t = map; //或者这样写using str_map_t = std::map;

    完整的代码如下:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. template<typename T>
    6. using str_map_t = map;
    7. int main()
    8. {
    9. str_map_t<int>mymap1;
    10. mapint>::iterator it;//迭代器
    11. mymap1.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
    12. mymap1.insert({ "helloworld",2 });
    13. mymap1.insert({ "abcdefghij",3 });
    14. for (it = mymap1.begin(); it != mymap1.end(); it++)//轮询输出容器里面的string字符串和int数据
    15. {
    16. cout << it->first;
    17. cout << " ";
    18. cout << it->second;
    19. cout << endl;
    20. }
    21. return 0;
    22. }

    我们把typedef和using来作比较如下:

    1. 1
    2. typedef unsigned int uint_t;
    3. using uint_t = unsigned int;
    4. 2
    5. typedef std::mapint> str_map_t;
    6. using str_map_t = std::mapint>;
    7. 3
    8. typedef int(*funType)(int,int);
    9. using funType = int(*)(int,int);

    类型相关的模板(给函数指针类型模板起别名)

    在.cpp中写如下代码:

    1. template<typename T>
    2. using myFunc = double(*)(T,T);
    3. double RealFunc(double i, double j)
    4. {
    5. return (i + j);
    6. }

    在main主函数中,增加如下代码:

    1. myFunc<double> pointFunc;
    2. pointFunc = RealFunc;
    3. cout << pointFunc(40.5, 49.5) << endl;

    总结:

    (1)用using定义类型相关模板与定义普通类型差不太多,只是在前面增加一个template开头的模板参数列表。

    (2)在using中使用的这种模板,既不是类模板,也不是函数模板,可以看成是一种新的模板形式--别名模板。

    二、显式指定模板参数

    类型模板参数是可以显示指定的。现在写一个函数来求和,可以指定返回的结果类型从而控制显示的精度。

    在.cpp文件中这样写:

    1. template<typename T1, typename T2, typename T3>
    2. T1 sum(T2 i,T3 j)
    3. {
    4. T1 result = i + j;
    5. return result;
    6. }

    在main主函数中这样写:

    1. auto result = sum(200000000, 200000000);
    2. cout << result << endl;

    编译代码,发现报错,提示“未找到匹配的重载函数”。观察可看到:T2和T3类型可以通过调用sum函数时的实参推断出来,但是T1没有办法通过函数实参推断出来。所以这里必须要至少给模板传一个模板参数T1:

    1. auto result = sum<int>(200000000, 200000000);
    2. cout << result << endl;

    编译后不报错了,但是结果却是-2094967296,不是我们想要的结果。int的取值范围是-2147483648~2147483647,而200000000加上200000000等于400000000已经超过int的取值范围,在sum中的int类型的result已经是装不了400000000我们可以这样写:

    1. auto result = sum<double,double,double>(200000000, 200000000);
    2. cout << result << endl;

    2022.08.12结。

  • 相关阅读:
    搜索店铺列表API 返回值说明
    53. 最大子序列和Maximum Subarray
    【Java】使用stream()串行和并行流,代替for循环一行写完
    基于Java+SpringBoot+mybatis+vue+element实现旅游管理系统
    JVM学习(宋红康)之运行时数据区之虚拟机栈中栈帧的动态链接及方法调用
    pytest学习和使用9-fixture中conftest.py如何使用?
    Java 21的StringBuilder和StringBuffer新增了一个repeat方法
    GBase8s数据库对 SET COLLATION 的限制
    python 库
    排序。。。。
  • 原文地址:https://blog.csdn.net/euxnijuoh/article/details/126295564