I have the following program:
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;
}
I could not figure out what part of the standard defines the ADL rule that says the call to foo(0)
should fail, while the call to foo(Foo())
should succeed. Can someone shed some light?
Reopened over my own deletion, eh? Well, after some prompting from juanchopanza, I read over the relevant part of the standard, C++11 §3.4.2, more carefully. I browsed it way too quickly before. To wit, paragraph 2 spells out:
For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way:
- If T is a fundamental type, its associated sets of namespaces and classes are both empty.
- If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces of which its associated classes are members. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members.
...
The first bullet explains why passing in an int
argument fails. The second bullet explains why passing in a Foo
instance works.