In his book The C++ Programming Language (third edition) Stroustrup teaches to define individual components in their own namespace and import them in a general namespac
Simply because nobody learns it. Most programmers are taught Java-style OOP, and it's more common to see C++ code which encapsulates a namespace-style API into a class
.
C++ has argument-dependent function lookup (ADL), which allows it to select a function from an API based on the namespaces of the types of the arguments it's called with. It's a powerful mechanism which allows you to bypass much of the OOP boilerplate yet retain the benefits. But it's not really taught to beginners, for no good particular reason.
For what it's worth, your example is roughly equivalent to this condensed version:
namespace api {
struct array {
friend void print(const array&) { }
};
struct list {
friend void print(const list&) { }
};
}
When you define a function as a friend
within a class, it belongs not to the class, but the enclosing namespace. Moreover, its name is available only within the class, not the enclosing namespace, except when it's called using the class as an argument.
Polluting the global namespace with array_api
and list_api
namespaces is a bad idea. Better to make a hierarchy as in my example.
So, given the above, you could do this:
api::array x;
print( x ); // ADL finds api::print defined inside api::array
Indeed, this is how the iostream-style operator <<
works. You don't need a using
declaration (or directive) to print objects from a library.