C++ 对参数相关查找和友元函数定义的混淆

C++ 对参数相关查找和友元函数定义的混淆,c++,c++11,language-lawyer,argument-dependent-lookup,C++,C++11,Language Lawyer,Argument Dependent Lookup,我有以下计划: struct Foo { friend void foo (int) {} operator int () const { return 0; } }; int main() { foo(Foo()); // This compiles fine foo(0); // This fails to find `foo()` return 0; } 我无法确定标准的哪一部分定义了ADL规则,即调用foo(0)应该失败,而调用fo

我有以下计划:

struct Foo {
    friend void foo (int) {}
    operator int () const { return 0; }
};

int main() {
    foo(Foo());  // This compiles fine
    foo(0);      // This fails to find `foo()`
    return 0;
}

我无法确定标准的哪一部分定义了ADL规则,即调用
foo(0)
应该失败,而调用
foo(foo())
应该成功。有人能解释一下吗?

我自己的删除重新打开了,嗯?在胡安科潘扎的提示下,我更仔细地阅读了标准的相关部分,C++11§3.4.2。我以前浏览得太快了。也就是说,第2款规定:

对于函数调用中的每个参数类型T,都有一组零个或多个关联的名称空间和一组零个或多个关联的类需要考虑。名称空间和类的集合完全由函数参数的类型(以及任何模板参数的名称空间)决定。Typedef名称和用于指定类型的使用声明不属于此集合。名称空间和类的集合按以下方式确定:

  • 如果T是基本类型,则其相关的名称空间集和类集都是空的
  • 如果T是类类型(包括联合),则其关联的类是:类本身;其所属类别(如有);以及它的直接和间接基类。其关联的名称空间是其关联的类所属的名称空间。此外,如果T是类模板专门化,则其关联的名称空间和类还包括:与为模板类型参数(不包括模板参数)提供的模板参数类型关联的名称空间和类;任何模板参数都是其成员的名称空间;以及任何用作模板参数的成员模板都是其成员的类

第一个项目符号解释了传递
int
参数失败的原因。第二个项目符号解释了为什么传入
Foo
实例有效。

查看代码:

int main() {
    foo(Foo());  // This declares a global function "foo" taking a "Foo" as an argument
    foo(0);      // "foo" takes a "Foo" above, and theres no way to convert an int to a Foo...

您是否清楚为什么
foo(0)
会失败,或者您也在问这个问题?@juanchopanza:我在问这两个问题。好吧,全局范围中没有
foo
的声明,所以…@juanchopanza:那么,如果函数参数涉及一个范围,那么该范围将添加到要搜索ADL匹配的范围集中?