From c69510e5911bf13a746d78b5b94566a8099aa303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=AB=E8=80=B3=E5=A0=80=E5=B7=9D=E9=9B=B7=E9=BC=93?= <58223265+neko-horikawaraiko@users.noreply.github.com> Date: Tue, 2 Feb 2021 21:15:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E8=AE=A2=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3.MovingToModernCpp/item9.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3.MovingToModernCpp/item9.md b/3.MovingToModernCpp/item9.md index eea45ee..b87b3e6 100644 --- a/3.MovingToModernCpp/item9.md +++ b/3.MovingToModernCpp/item9.md @@ -71,7 +71,7 @@ private: ... //没有“::type” }; ```` -对你来说,`MyAllocList`(使用了模板别名声明的版本)可能看起来和`MyAllocList::type`(使用`typedef`的版本)一样都应该依赖模板参数`T`,但是你不是编译器。当编译器处理`Widget`模板时遇到`MyAllocList`(使用模板别名声明的版本),它们知道`MyAllocList`是一个类型名,因为**MyAllocList**是一个别名模板:它**一定**是一个类型名。因此`MyAllocList`就是一个**非依赖类型**(*non-dependent type*),就不需要也不允许使用`typename`修饰符。 +对你来说,`MyAllocList`(使用了模板别名声明的版本)可能看起来和`MyAllocList::type`(使用`typedef`的版本)一样都应该依赖模板参数`T`,但是你不是编译器。当编译器处理`Widget`模板时遇到`MyAllocList`(使用模板别名声明的版本),它们知道`MyAllocList`是一个类型名,因为`MyAllocList`是一个别名模板:它**一定**是一个类型名。因此`MyAllocList`就是一个**非依赖类型**(*non-dependent type*),就不需要也不允许使用`typename`修饰符。 当编译器在`Widget`的模板中看到`MyAllocList::type`(使用`typedef`的版本),它不能确定那是一个类型的名称。因为可能存在一个`MyAllocList`的它们没见到的特化版本,那个版本的`MyAllocList::type`指代了一种不是类型的东西。那听起来很不可思议,但不要责备编译器穷尽考虑所有可能。因为人确实能写出这样的代码。 @@ -105,7 +105,7 @@ std::add_lvalue_reference::type //从T中产出T& 尽管写了一些,但我这里不是想给你一个关于*type traits*使用的教程。注意类型转换尾部的`::type`。如果你在一个模板内部将他们施加到类型形参上(实际代码中你也总是这么用),你也需要在它们前面加上`typename`。至于为什么要这么做是因为这些C++11的*type traits*是通过在`struct`内嵌套`typedef`来实现的。是的,它们使用类型同义词(译注:根据上下文指的是使用`typedef`的做法)技术实现,而正如我之前所说这比别名声明要差。 -关于为什么这么实现是有历史原因的,但是我们跳过它(我认为太无聊了),因为标准委员会没有及时认识到别名声明是更好的选择,所以直到C++14它们才提供了使用别名声明的版本。这些别名声明有一个通用形式:对于C++11的类型转换`std::`transformation`::type`在C++14中变成了`std::`transformation**`_t`**。举个例子或许更容易理解: +关于为什么这么实现是有历史原因的,但是我们跳过它(我认为太无聊了),因为标准委员会没有及时认识到别名声明是更好的选择,所以直到C++14它们才提供了使用别名声明的版本。这些别名声明有一个通用形式:对于C++11的类型转换`std::`transformation`::type`在C++14中变成了`std::`transformation`_t`。举个例子或许更容易理解: ````cpp std::remove_const::type //C++11: const T → T