Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is namespace composition so rarely used?

Tags:

c++

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 namespace.

For example:

namespace array_api {    
    struct array {};    
    void print(const array&) { }
}

namespace list_api {
    struct list {};        
    void print(const list&) { }
}

namespace api {
    using array_api::array;
    using list_api::list;
}

I looks interesting, but I have never seen this approach used in practice.

Why is this technique is almost never used?

like image 820
StackedCrooked Avatar asked Jun 01 '13 09:06

StackedCrooked


People also ask

Why namespace is not used in C?

The problem with putting using namespace in the header files of your classes is that it forces anyone who wants to use your classes (by including your header files) to also be 'using' (i.e. seeing everything in) those other namespaces.

What is the main purpose of the namespace?

Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.

What can I use instead of namespace std?

The alternative is to write std:: everywhere.

What are the benefits of using namespaces?

Advantages of namespace In one program, namespace can help define different scopes to provide scope to different identifiers declared within them. By using namespace - the same variable names may be reused in a different program.


2 Answers

Mostly I wonder what the benefits would be (as Raymond Chen says, every feature starts with -100 points). However, I have a counterpoint to offer: Luabind, which does use something that looks like this. See luabind/object.hpp, which essentially says:

namespace luabind {
  namespace adl {
    class object {
    };
  }
  using adl::object;
}

From the name alone we can infer the motivation: to support argument-dependent lookup. Given what the user knows as a luabind::object, which is actually a luabind::adl::object, related functions will be discovered automatically by the compiler from the luabind::adl namespace. Yet those functions, which the user may not need to know about in a very explicit way, do not "pollute" the main luabind namespace. So that's nice, I guess.

But you know what's not nice? Forward declaring one of these classes. This fails:

namespace luabind { class object; }

You need to do this instead:

namespace luabind { namespace adl { class object; } }

Thus the abstraction quickly leaks, as the user does need to know about this magic adl namespace after all.

like image 195
John Zwinck Avatar answered Oct 06 '22 04:10

John Zwinck


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.

like image 42
Potatoswatter Avatar answered Oct 06 '22 04:10

Potatoswatter