Update item30.md (#144)

This commit is contained in:
Xingyu Feng 2023-02-19 12:14:51 +08:00 committed by GitHub
parent 2492e6463b
commit 1c9d4ba5b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -65,8 +65,8 @@ fwd({ 1, 2, 3 }); //错误!不能编译
当通过调用函数模板`fwd`间接调用`f`时,编译器不再把调用地传入给`fwd`的实参和`f`的声明中形参类型进行比较。而是**推导**传入给`fwd`的实参类型,然后比较推导后的实参类型和`f`的形参声明类型。当下面情况任何一个发生时,完美转发就会失败:
- **编译器不能推导出`fwd`的一个或者多个形参类型。**这种情况下代码无法编译。
- **编译器推导“错”了`fwd`的一个或者多个形参类型。**在这里,“错误”可能意味着`fwd`的实例将无法使用推导出的类型进行编译,但是也可能意味着使用`fwd`的推导类型调用`f`,与用传给`fwd`的实参直接调用`f`表现出不一致的行为。这种不同行为的原因可能是因为`f`是个重载函数的名字,并且由于是“不正确的”类型推导,在`fwd`内部调用的`f`重载和直接调用的`f`重载不一样。
- **编译器不能推导出`fwd`的一个或者多个形参类型。** 这种情况下代码无法编译。
- **编译器推导“错”了`fwd`的一个或者多个形参类型。** 在这里,“错误”可能意味着`fwd`的实例将无法使用推导出的类型进行编译,但是也可能意味着使用`fwd`的推导类型调用`f`,与用传给`fwd`的实参直接调用`f`表现出不一致的行为。这种不同行为的原因可能是因为`f`是个重载函数的名字,并且由于是“不正确的”类型推导,在`fwd`内部调用的`f`重载和直接调用的`f`重载不一样。
在上面的`fwd({ 1, 2, 3 })`例子中,问题在于,将花括号初始化传递给未声明为`std::initializer_list`的函数模板形参,被判定为——就像标准说的——“非推导上下文”。简单来讲,这意味着编译器不准在对`fwd`的调用中推导表达式`{ 1, 2, 3 }`的类型,因为`fwd`的形参没有声明为`std::initializer_list`。对于`fwd`形参的推导类型被阻止,编译器只能拒绝该调用。