typedef一般用来定义类型别名,如
typedef unsigend int uint_t;
这里我们先演示一下map容器的简单应用,程序如下:
- #include
- #include
- #include
-
- using namespace std;
-
- int main()
- {
- map
int> mymap;//定义一个map类型的mymap容器 - map
int>::iterator it;//迭代器 -
- mymap.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
- mymap.insert({ "helloworld",2 });
- mymap.insert({ "abcdefghij",3 });
-
- for(it=mymap.begin();it!= mymap.end();it++)//轮询输出容器里面的string字符串和int数据
- {
- cout << it->first;
- cout << " ";
- cout << it->second;
- cout << endl;
- }
- return 0;
- }
如果在实际开发有这样一个需求:希望定义一个类型,但这个类型不固定,例如对于map类型容器中的元素,元素的键(key)固定是std::string类型,但是值(value)不希望固定为int或者固定为string类型,希望可以自己自由指定。
这个需求通过typedef不好做到,因为typedef一般都是用来给固定类型起别名,二这里的类型名不固定,像一个模板一样。在C++98标准中,开发者通过一个变通的办法来达到这个目的,通过一个类模板来实现,在.cpp文件中这样写:
- #include
- #include
- #include
-
- using namespace std;
-
- template<typename wt>
- class map_struct
- {
- public:
- typedef map
type;//或typedef std::map type; - };
-
- int main()
- {
- map_struct<int>::type mymap;
- map
int>::iterator it;//迭代器 -
- mymap.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
- mymap.insert({ "helloworld",2 });
- mymap.insert({ "abcdefghij",3 });
-
- for (it = mymap.begin(); it != mymap.end(); it++)//轮询输出容器里面的string字符串和int数据
- {
- cout << it->first;
- cout << " ";
- cout << it->second;
- cout << endl;
- }
- return 0;
- }
可以看到,为了实现这种比较通用的以string类型为key,以任意类型为value的map容器,不得不写一个类模板来达到此目的。
在C++11的新标准使类似的问题解决起来变得非常简单,不用定义类模板了,如下两行代码就解决问题:
- template<typename T>
- using str_map_t = map
; //或者这样写using str_map_t = std::map;
完整的代码如下:
- #include
- #include
- #include
-
- using namespace std;
-
- template<typename T>
- using str_map_t = map
; -
- int main()
- {
- str_map_t<int>mymap1;
- map
int>::iterator it;//迭代器 -
- mymap1.insert({ "1234567890",1 });//往容器里面插入string字符串和int类型数据
- mymap1.insert({ "helloworld",2 });
- mymap1.insert({ "abcdefghij",3 });
-
- for (it = mymap1.begin(); it != mymap1.end(); it++)//轮询输出容器里面的string字符串和int数据
- {
- cout << it->first;
- cout << " ";
- cout << it->second;
- cout << endl;
- }
-
- return 0;
- }
我们把typedef和using来作比较如下:
- (1)
- typedef unsigned int uint_t;
- using uint_t = unsigned int;
-
- (2)
- typedef std::map
int> str_map_t; - using str_map_t = std::map
int>; -
- (3)
- typedef int(*funType)(int,int);
- using funType = int(*)(int,int);
类型相关的模板(给函数指针类型模板起别名)
在.cpp中写如下代码:
- template<typename T>
- using myFunc = double(*)(T,T);
-
- double RealFunc(double i, double j)
- {
- return (i + j);
- }
在main主函数中,增加如下代码:
- myFunc<double> pointFunc;
-
- pointFunc = RealFunc;
- cout << pointFunc(40.5, 49.5) << endl;
总结:
(1)用using定义类型相关模板与定义普通类型差不太多,只是在前面增加一个template开头的模板参数列表。
(2)在using中使用的这种模板,既不是类模板,也不是函数模板,可以看成是一种新的模板形式--别名模板。
类型模板参数是可以显示指定的。现在写一个函数来求和,可以指定返回的结果类型从而控制显示的精度。
在.cpp文件中这样写:
- template<typename T1, typename T2, typename T3>
- T1 sum(T2 i,T3 j)
- {
- T1 result = i + j;
- return result;
- }
在main主函数中这样写:
- auto result = sum(200000000, 200000000);
- cout << result << endl;
编译代码,发现报错,提示“未找到匹配的重载函数”。观察可看到:T2和T3类型可以通过调用sum函数时的实参推断出来,但是T1没有办法通过函数实参推断出来。所以这里必须要至少给模板传一个模板参数T1:
- auto result = sum<int>(200000000, 200000000);
- cout << result << endl;
编译后不报错了,但是结果却是-2094967296,不是我们想要的结果。int的取值范围是-2147483648~2147483647,而200000000加上200000000等于400000000已经超过int的取值范围,在sum中的int类型的result已经是装不了400000000,我们可以这样写:
- auto result = sum<double,double,double>(200000000, 200000000);
- cout << result << endl;
2022.08.12结。