【发布时间】:2019-03-21 16:25:49
【问题描述】:
本题基于 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) 是后缀表达式。
那么postfix-expression的语法类别定义为
后缀表达式:
主表达式
后缀表达式[表达式]
后缀表达式 [braced-init-list ]
后缀表达式(表达式列表选择)
简单类型说明符(表达式列表选择)
类型名说明符(表达式列表选择)
简单类型说明符花括号初始化列表
类型名称说明符花括号初始化列表
后缀表达式。模板 opt id 表达式
后缀表达式 -> 模板选择 ID 表达式
后缀表达式。伪析构函数名
后缀表达式 -> 伪析构函数名称
后缀表达式 ++
后缀表达式--
dynamic_cast (表达式)
static_cast ( 表达式 )
reinterpret_cast (表达式)
const_cast ( 表达式 )
typeid(表达式)
typeid ( type-id )
在这种情况下,只有 primary-expression 是相关的。它被定义为
主表达式:
字面意思
这个
(表达式)
id 表达式
lambda 表达式
在这种情况下,只有 id-expression 是相关的,它被定义为
id 表达式:
不合格的 ID
合格 ID
所以f 和(f) 就是其中之一。如果(f) 不是非限定ID(因为ADL 被抑制),它应该是qualified-id 之一。但它被定义为
合格ID:
:: opt nested-name-specifier template opt unqualified-id
:: 标识符
:: operator-function-id
:: literal-operator-id
:: 模板 ID
我认为(f) 不是其中之一。如果是这样,为什么(f)(s) 会抑制 ADL?
补充:
This answer(在this comment中给出)说
如标准附录 A 中所述,
(expression)形式的post-fix expression是primary expression,但不是id-expression,因此不是unqualified-id。这意味着与常规形式fun(arg)相比,在形式为(fun)(arg)的函数调用中阻止了依赖于参数的名称查找。
但它是正确的吗? 表达式的语法类别定义为
表达式:
赋值表达式
表达式,赋值表达式
在附件 A 中。我认为 (f) 中的 f 不是表达式之一。
【问题讨论】:
-
已回复here。想看看有没有更好的目标
标签: c++ language-lawyer