Skip to content

84 Advanced The Hundred

The Function You Never Imported

you have been relying on this since your first hello world

#include <iostream>

namespace geo {
struct Point {
    int x, y;
};

void describe(Point p) { std::cout << "point at (" << p.x << ", " << p.y << ")\n"; }
}   // namespace geo

int main() {
    geo::Point p{3, 4};
    describe(p);
    std::operator<<(std::cout, "hello, fully qualified\n");
}

Run it. Does it even compile?

Answer

Yes — both lines. It prints point at (3, 4) and hello, fully qualified, even though main never wrote geo:: or using for describe.

Why

When a call is unqualifieddescribe(p), not geo::describe(p)argument-dependent lookup (ADL) makes the compiler search not just the enclosing scopes but also the namespaces of the argument types. p is a geo::Point, so geo::describe is found with no import at all. You exploit this in every program: std::cout << "hi" prints the text only because ADL finds the free operator<<(ostream&, const char*) in namespace std — the last line of the demo is that exact call with its full name spelled out. Without ADL the line would still compile: member-only lookup falls back to basic_ostream::operator<<(const void*), so std::cout.operator<<("hi") prints the pointer's address (something like 0x402010) instead of hi. The flip side is that ADL can silently pull in an unintended overload from an argument's namespace. Deliberately inviting ADL is also what the classic two-step using std::swap; swap(a, b); is for: the unqualified call lets ADL find a type's own swap, with std::swap as the fallback.

The fix

Nothing here is broken — but when you want lookup on a leash, qualify the call, and when you want ADL on purpose, use the two-step:

geo::describe(p);              // qualified: lookup goes exactly where you point
using std::swap; swap(a, b);   // ADL first, std::swap as the fallback

Takeaway: for unqualified calls, a function effectively lives in the namespace of its argument types — lookup follows the arguments home.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry