你好,我是雨乐!
今天我们聊点点的知识点typedef & using😁。
C语言支持类型别名typedef,显然,CPP也支持咯。不过自CPP11(也称之为Modern CPP
)开始,引入了using关键字用以表示类型别名。
typedef和using都可以创建类型别名,区别是在语法语义上的不同。
typedef的语法如下:
typedef [original-type] [alias];
用法如下:
typedef int MyInt;
typedef std::map<std::string, std::vector<std::string>> Map;
MyInt a = 3;
Map m;
using的语法如下:
using [alias] = [original-type];
用法如下:
using MyInt = int;
using Map = std::map<std::string, std::vector<std::string>>;
MyInt a = 3;
Map m;
从上述示例看出,无论是使用typedef还是using都创建一个类型别名,他们的使用方式是一样的。也就是说到目前为止,看起来 typedef 和用法是相同的,但存在即合理,对using的引入肯定有其他原因,这就引入了typedef和using在模板别名上的不同。
在前面的例子中,通过typedef和using创建了std::map<std::string, std::vector<std::string>>
的别名Map,但是这个Map的类型是固定的,也就是说只能应用于key是string,value为std::vector<std::string>的map,如果要创建一个std::map<int, std::vector<int>>
的别名,就需要重新声明,就像下面这种:
typedef std::map<int, std::vector<int>> Map1;
using Map2 = std::map<int, std::vector<int>>;
显然,这张重新声明别名的方式在通用性上很差,所以为了解决通用性问题,就需要使用template
。
幸运的是,using可以直接创建模板别名:
template<[template-parameter-list]> using [your-alias] = [original-type];
比如:
template<typename T1, typename T2> using Map = std::map<T1, std::vector<T2>>;
Map<int, int> m;
此时,你可能会问typedef是不是也可以创建模板类型别名?当然可以,但是相对于using,typedef创建模板类型别名会麻烦很大。
如果要使用typedef创建模板类型别名,就需要创建一个模板类,这个别名的声明需要封装在结构体中,如下:
template<typename T1, typename T2>
struct KV{
typedef std::map<T1, std::vector<T2>> type;
};
KV<int, std::string>::type Map;
在此,我们引入标准中的一句话作为本文的结语:
A typedef-name can also be introduced by an alias-declaration. The identifier following the *using* keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier. In particular, it does not define a new type and it shall not appear in the type-id.
也就是说在typedef和using在语义是一样的,只是后者的引入更为方便使用而已。
以上~~
今天的文章就到这,我们下期见!
推荐阅读 点击标题可跳转