首页 > 编程 > C++ > 正文

Effective Modern C++ 条款9补完 理解模板类型推断

2019-11-11 07:51:21
字体:
来源:转载
供稿:网友

http://blog.csdn.net/big_yellow_duck/article/details/52224068

看大黄鸭的《Effective Modern C++》翻译时,第9款最后有一小部分没有翻,于是去看英文版补全,

看的时候顺便翻译了一下。然后今天校对过后把它发出来。

条款9  理解模板类型推断  (最后小半部分)

如果你做过模板元编程(templete meta PRogramming, TMP),你肯定会遇到过要把模板类型转换为其他类型的需求。例如,对于类型T,你可能想要去除T含有的const 修饰或者引用修饰,具体来说,比如你可能会想把const string& 变成std::string。或者你也有可能想把一个类型加上const修饰或者左值引用修饰,具体来说,比如把Widget变成const Widget或者Widget&。(如果你还没有碰到过模板元编程,那可真是太糟糕了,因为如果你想成为真正高效的C++程序员,你就需要对c++的这一块至少有最基本的了解。你会在条款25和条款29中也看到TMP的例子,其中也包含了我在上面提及到的类型转换。

c++11提供了实行这样转换的工具,他们叫做type traits,是一种变形的模板类,包含在头文件<type_traits>中。这个头文件中有一打这样的type traits,但并不是所有的都是处理类型转换相关,其中的一些提供了望文而知意的接口。假设你要转换的源类型为T,你需要的转换结果就是std::transformation<T>::type。例如:

std::remove_const<T>::type // yields T from const T

std::remove_reference<T>::type // yields T from T& and T&&

std::add_lvalue_reference<T>::type // yields T& from T

上面的注释只是简单说明代码做了什么。不要在意我的修辞手法。不过在把他们用到工程中之前,你一定去会仔细查阅他们的说明文档的,这我知道。

不过我在这里的原意也不是上一堂关于type traits的教学课。我请你注意到这些转换接口的末尾都带有“::type”的后缀。如果你用它们在模板内部作为参数传递(实际上你总是这样使用它们),你也不得不在每个前面加上一个“typename”。会出现这样像是马路两边的“路牙”的玩意,是因为c++11的type traits的实现,是基于模板化结构的内部嵌套typedef。没错,那就是我曾经极力向你推荐的类型变化技巧,现在他们输给了模板别名(alias template)!!(译注:即using关键字)

c++11这样做是有历史原因的,不过我们先跳过他们(说明很无趣,我保证)。长话短说,因为c++标准化委员会终于认识到模板别名是更好的实现方案,他们于是先在c++14里为这些c++11风格的类型转换做了一层包装。包装具有如下形式:对每个c++11形如std::transformation<T>::type的转换接口,就有一个与之对应的C++14 模板别名std::transformation_t。看例子就知道我说的意思了。

std::remove_const<T>::type // C++11: const T → T

std::remove_const_t<T> // C++14 equivalent

std::remove_reference<T>::type // C++11: T&/T&& → T

std::remove_reference_t<T> // C++14 equivalent

std::add_lvalue_reference<T>::type // C++11: T →T&

std::add_lvalue_reference_t<T> // C++14 equivalent

c++11形式的接口在c++14里还能用,不过我想不出你还有什么理由用他们。即使你没有c++14,你自己写一个模板别名也是小菜一碟。这只需要用到c++11的语言特性,连三岁小孩也能做到的,相信我。即使你能拿到一份c++14标准案的拷贝,也还是自己写比较简单,因为所有你要做的就是拷贝粘贴。我会给你起个头(也是通过拷贝粘贴):

template <class T>using remove_const_t = typename remove_const<T>::type;

template <class T>using remove_reference_t = typename remove_reference<T>::type

template <class T>using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;

你瞧,简单得不能再简单了吧。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选