此问题基于C ++ 11标准(N3092)。
3.4.2-1 依赖于参数的名称查找说
当函数调用(5.2.2)中的postfix-expression是不合格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 的语法类别定义为
后缀表达式:
主要表达式
postfix-expression [表达式]
postfix-expression [braced-init-list]
后缀表达式(expression-list opt)
简单类型说明符(expression-list opt)
typename-specifier(expression-list opt)
简单类型说明符braced-init-list
typename-specifier braced-init-list
后缀表达式。模板opt id-expression
postfix-expression->模板opt id-expression
后缀表达式。伪析构函数名称
postfix-expression->伪析构函数名称
后缀表达式++
后缀表达式-
dynamic_cast
(表达式) static_cast
(表达式) reinterpret_cast
(表达式) const_cast
(表达式) typeid(表达式)
typeid(type-id)
在这种情况下,只有 primary-expression 是相关的。定义为
主要表达式:
文字
此
(表达式)
id-expression
lambda表达式
在这种情况下,只有 id-expression 是相关的,并且定义为
id-expression:
不合格ID
qualified-id
因此f
和(f)
是其中之一。如果(f)
不是不合格ID(因为ADL被抑制),则它应该是 qualified-id 之一。但是它定义为
qualified-id:
:: opt嵌套名称说明符模板opt unqualified-id
::标识符
::操作员功能ID
::文字运算符ID
::模板ID
我认为(f)
不是其中之一。如果是这样,为什么(f)(s)
抑制ADL?
补充:
This answer(在this comment中给出)说
如本标准附录A中所述,
post-fix expression
形式的(expression)
是primary expression
,但不是id-expression
,因此不是{{ 1}}。这意味着与常规形式unqualified-id
相比,在形式为(fun)(arg)
的函数调用中可以防止依赖于参数的名称查找。
但这是正确的吗? expression 的语法类别定义为
附件A中的表达式:
分配表达式
表达式,赋值表达式
。我认为fun(arg)
中的f
不是表达式之一。
答案 0 :(得分:1)
(f)
是(
表达式 )
,而不是 unqualified-id ,因此ADL不适用。带括号的 unqualified-id 不再是 unqualified-id 。在某些情况下,该标准表示“可能用括号括起来的” X等效于X。依赖于参数的查找不是其中一种情况。