Reputation: 179
I've been reading through the namespace chapter in The C++ Programming Language by Bjarne Stroustrup and got confused about how functions get called using Argument-Dependent Lookup. The following are code snippets from the book:
Snippet 1
namespace Chrono {
class Date { /* ... */ };
bool operator==(const Date&, const std::string&);
std::string format(const Date&); // make string representation
// ...
}
void f(Chrono::Date d, int i)
{
std::string s = format(d); // Chrono::format()
std::string t = format(i); // error: no format() in scope
}
This snippet makes sense to me since Chrono is a namespace used in the function f's arguments and therefore it is searched successfully for a format(Date) function. It also appears the function f and namespace Chrono share the same scope, which confuses me about the next snippet:
Snippet 2
namespace N {
struct S { int i };
void f(S);
void g(S);
void h(int);
}
struct Base {
void f(N::S);
};
struct D : Base {
void mf();
void g(N::S x)
{
f(x); // call Base::f()
mf(x); // call D::mf()
h(1); // error: no h(int) available
}
};
This makes sense to me up until the line "h(1);" Since both structs and namespace N share the same scope, why can't the function "void h(int)" be found in namespace N?
Stroustrup does go on to say that "If an argument is a member of a namespace, the associated namespaces are the enclosing namespaces." Since the argument to g is a member of namespace N, does this mean the enclosing namespace is the global namespace which does not contain a function "h(int)"? If that's the case, why wouldn't Snippet 1 fail if the enclosing namespace is the global namespace which also doesn't include a "format(Date)" function?
Thanks in advance for insight into this matter!
Upvotes: 2
Views: 644
Reputation: 137404
ADL applies based on the types of the arguments in the call itself, not the types of the parameters of the function the call may or may not be in.
In format(d)
, format
is looked up in Chrono
because an argument to that call, d
, is of the type Chrono::Date
, and Chrono
is an associated namespace of that type. Whether the function containing the call is void f(Chrono::Date d, int i)
or void f()
is irrelevant. (Obviously, in the latter case, assuming that there's a Chrono::Date d;
.)
Upvotes: 2