inline constexpr auto makeFoo = [](auto const& x) {
return getFoo(x);
};
inline constexpr auto getFoo = [](int const&) {
return 1;
};
int bar() {
return makeFoo(32);
}
我理解,基于对两阶段名称查找的“非正式”理解:
makeFoo
是一个通用的 lambda,并且getFoo
在其主体中对类型尚不清楚的参数进行调用,因此getFoo
还不能查找名称;- 当看到调用时
makeFoo(32)
,lambdaoperator()
会被实例化auto = int
,因此会发生对非限定名称的第二阶段查找getFoo
; - 然而,这只是 ADL,所以它找不到
getFoo
,因为那是 lambda 的名称,即对象的名称,而不是函数的名称。
有人可以指导我找到“反映”上述解释的标准草案部分吗?
我认为[basic.lookup.unqual]和[temp.dep.res]可能包含解释该案例所需的所有内容,但我无法将这些部分拼凑在一起。
参数依赖查找的作用是:
即使不关注我们所寻找的细节,依赖于参数的查找也只会找到函数和函数模板的声明。
getFoo
既不是函数也不是函数模板,它是一个对象 - 所以它永远不会被发现。因此,如果您想要
getFoo
被找到,就必须通过常规查找来找到它 - 它的声明必须在其调用之前。getFoo(x)
就是所谓的依赖调用。正如[temp.dep.general]注释1所述,以及[temp.res.general]解释的那样:这基本上意味着由于名称查找被延迟,所以内部
getFoo
不会立即出现错误。makeFoo
该
auto const&
参数构成makeFoo
一个泛型 lambda 表达式,因此闭包类型的调用运算符是一个模板。效果就像你写了类似这样的东西:由于[temp.dep.candidate] p1 ,这是有问题的:
getFoo
是出现在模板声明中的名称,因此它会在 中查找makeFoo
,而不是在稍后getFoo
可见的位置查找。这会导致实例化 后程序格式错误operator()<int>()
。关于参数相关查找的注意事项
getFoo
正如您所指出的,ADL 有一些特殊规则,如果ADL 找到了该程序,这些规则将使该程序有效。这些特殊规则可以在[basic.lookup.argdep] p4中找到。