比起typedef,谁更偏爱别名声明?
摘要:本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误。谢谢! 博客已经迁移到 "这里啦" 我确信我们都
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误。谢谢!
博客已经迁移到这里啦
我确信我们都同意使用STL容器是一个好主意,并且我希望在Item 18中能让你相信使用std::unique_ptr也是一个好主意,但是我猜想,我们中没有任何一个人想多次写这样的类型:“std::unique_ptr<std::unordered_map<std::string, std::string>>”。光是想想就感觉,得“腕管综合症”的风险会增加。
为了避免这样的医学上的悲剧很简单,引进typedef:
typedef
std::unique_ptr<std::unordered_map<std::string, std::string>>
UPtrMapSS;
但是typedef太太太C++98了。当然,它们能在C++11中工作,但是C++11也提供了别名声明(alias declaration):
using UPtrMapSS =
std::unique_ptr<std::unordered_map<std::string, std::string>>;
给出的typedef和别名声明(alias declaration)做的是同样的事情,这值得我们去考虑这里是否有什么科学的原因来让我们更偏爱其中一个。
是的,但是在我说明之前,我想谈一下别的:很多人发现在涉及函数指针的时候,别名声明(alias declaration)更好接受一点:
//FP 是指向一个函数的指针的别名,这个函数以一个int和一个
//const std::string&为参数,不返回任何东西。
typedef void (*FP)(int, const std::string&); //typedef
//和上面同样的意义
using FP = void(*)(int, const std::string&): //别名声明
当然,这两个都很容易接受,并且不管怎么说,很少人需要花费大量的时间学习使用函数指针类型的别名,所以这几乎不是一个强硬的理由来让我们选择别名声明(alias declaration)替换typedef。
但是强硬的理由是存在的:template。尤其是,别名声明(alias declaration)能模板化(我们称之为别名模板(alias template)),但是typedef不能这么做。这给了C++11程序员一个简单的机制来表达在C++98中必须使用嵌套在模板化struct中的typedef来做的事情。举个例子,考虑定义一个链表的别名,这个链表使用自定义的分配器(allocator)MyAlloc。使用别名声明(alias declaration),这就是小case:
//MyAllocList<T>就是std::list<T, MyAlloc<T>>的别名
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>;
MyAllocList<Widget> lw; //客户代码
使用typedef,你就有麻烦了:
//MyAllocList<T>::type就是std::list<T, MyAlloc<T>>的别名
template<typename T>
struct MyAllocList{
typedef std::list<T, MyAlloc<T>> type;
};
MyAllocList<Widget>::type lw; //客户代码
如果你想在template中使用typedef来达到 使用template参数作为链表的模板类型参数 来创建别名的目的,这将变得更糟糕,你必须在typedef前面加上typename:
//Widget中有一个MyAllocList<T>作为成员变量
template<typename T>
class Widget{
private:
typename MyAllocList<T>::type list;
...
};
这里,MyAllocList::type引用的是一个类型依赖于template的参数(T)。
