为什么在这种情况下不考虑依赖于参数的查找?
Why in this case does argument-dependent lookup not considered?
此问题基于 C++11 标准 (N3092)。
3.4.2-1依赖于参数的名称查找说
当函数调用 (5.2.2) 中的后缀表达式是非限定 id 时,可能会搜索在通常的非限定查找 (3.4.1) 期间未考虑的其他命名空间,并且在这些命名空间中,可能会找到不可见的命名空间范围友元函数声明 (11.4)。对搜索的这些修改取决于参数的类型(对于模板模板参数,则取决于模板参数的命名空间)。[ 示例:
namespace N {
struct S { };
void f(S);
}
void g() {
N::S s;
f(s); // OK: calls N::f
(f)(s); // error: N::f not considered; parentheses
// prevent argument-dependent lookup
}
— 结束示例 ]
,但我不明白为什么(f)(s)
抑制 ADL(依赖于参数的查找)。这就是我想问的。
根据 5.2.2-1函数调用,
函数调用是一个后缀表达式,后跟括号,其中包含可能为空的逗号分隔的表达式列表,这些表达式构成函数的参数。
因此,在这种情况下,f
或(f)
是后缀表达式。
然后后缀表达式的语法类别定义为
后缀表达式:
初级表达
后缀表达式 [ 表达式 ]
后缀表达式 [ 大括号初始化列表 ]
后缀表达式 ( 表达式列表选项 )
简单类型说明符 ( 表达式列表选项 )
类型名称说明符 ( 表达式列表选项 )
简单类型说明符大括号初始化列表
类型名说明符大括号初始化列表
后缀表达式 。模板 opt ID 表达式
后缀表达式 -> 模板 opt ID 表达式
后缀表达式 。伪析构函数名称
后缀表达式 ->伪析构函数名称
后缀表达式 ++
后缀表达式 --
dynamic_cast<类型 ID=">( 表达式 )类型>
static_cast<类型 ID=">( 表达式 )类型>
reinterpret_cast<类型 ID=">( 表达式 )类型>
const_cast<类型 ID=">( 表达式 )类型>
类型标识 ( 表达式 )
类型标识 ( 类型标识 )
在这种情况下,只有主要表达式是相关的。它被定义为
主要表达式:
字面
这
( 表达式 )
身份表达式
λ表达式
在这种情况下,只有id-expression是相关的,它被定义为
id-表达式:
非限定标识
限定标识
所以f
和(f)
就是其中之一。如果(f)
不是非限定 id(因为 ADL 被抑制),则它应该是限定 id之一。但它被定义为
限定标识:
:: 选择嵌套名称说明符模板 选择非限定 ID
::标识符
:: 运算符函数 ID
:: 文字运算符 ID
:: 模板标识
我认为(f)
不是其中之一。如果是这样,为什么(f)(s)
抑制ADL?
补充:
这个答案(在此评论中给出)说
正如标准附录A所详述的,
(expression)
形式的post-fix expression
是primary expression
,但不是id-expression
,因此不是unqualified-id
。这意味着与传统形式fun(arg)
相比,在形式(fun)(arg)
的函数调用中阻止了与参数相关的名称查找。
但这是正确的吗?表达式的语法类别定义为
表达:
赋值表达式
表达式 , 赋值表达式
见附件A。我不认为f
(f)
是一种表达。
(f)
(
表达式)
,而不是非限定 id,因此 ADL 不适用。带括号的非限定 id不再是非限定 id。在某些情况下,标准说"可能括起来的"X等同于X.依赖于参数的查找不是这些情况之一。
- 参数相关查找和流运算符重载
- 编译器在C++中调用另一个函数时,在参数中查找已删除的构造函数
- 当数组在C++中用作参数时,查找数组的元素数
- C++ 普通查找与参数相关查找
- 运算符<<依赖于参数的查找不在全局命名空间中查找
- 查找可变参数列表的字符串格式指定符
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- 如何查找/删除具有特定参数的结构向量的元素
- C 中的参数查找
- 支持与参数有关的查找的编译器
- 为什么在其他函数中声明的函数不参与参数相关查找?
- 使用查找表选择具有运行时索引的可变参数类型
- 为什么在这种情况下不考虑依赖于参数的查找?
- 数组作为函数参数查找数组长度时出错
- 仅通过参数查找重载地址
- 重载函数查找轮廓的实例与参数列表不匹配
- 我如何避免使用依赖于参数的查找明确专门化模板化功能
- 查找参数包的唯一值的数目
- 查找参数时出错
- 用于查找参数是否为类的不同模板语法