C++ Namespaces Advice

C++ namespaces advice

C++ namespaces were not intended to be a design mechanism - they are there simply to prevent name clashes. You really don't want or need to use nested namespaces in 99.99% of situations.

A good example of the correct use of namespaces in C++ is the C++ Standard Library. Everything in this quite large library is placed in a single namespace called std - there is no attempt or need to break the library up into (for example) an I/O sub-namespace, a math sub-namespace, a container sub-namespace etc.

The basic tool for modelling in C++ is the class (and to some extent the template), not the namespace. If you feel the need for nesting, you should consider using nested classes, which have the following advantages over namespaces:

  • they have methods
  • they can control access
  • they cannot be re-opened

Having considered these, if you still wish to use nested namespaces by all means do so - there is nothing technically wrong with using them in this way.

How do you properly use namespaces in C++?

Namespaces are packages essentially. They can be used like this:

namespace MyNamespace
{
class MyClass
{
};
}

Then in code:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

Or, if you want to always use a specific namespace, you can do this:

using namespace MyNamespace;

MyClass* pClass = new MyClass();

Edit: Following what bernhardrusch has said, I tend not to use the "using namespace x" syntax at all, I usually explicitly specify the namespace when instantiating my objects (i.e. the first example I showed).

And as you asked below, you can use as many namespaces as you like.

Is there a better way to express nested namespaces in C++ within the header

C++17 might simplify nested namespace definition:

namespace A::B::C {
}

is equivalent to

namespace A { namespace B { namespace C {
} } }

See (8) on namespace page on cppreference:

http://en.cppreference.com/w/cpp/language/namespace

Why is using namespace std; considered bad practice?

Consider two libraries called Foo and Bar:

using namespace foo;
using namespace bar;

Everything works fine, and you can call Blah() from Foo and Quux() from Bar without problems. But one day you upgrade to a new version of Foo 2.0, which now offers a function called Quux(). Now you've got a conflict: Both Foo 2.0 and Bar import Quux() into your global namespace. This is going to take some effort to fix, especially if the function parameters happen to match.

If you had used foo::Blah() and bar::Quux(), then the introduction of foo::Quux() would have been a non-event.

c++ namespace best practice dilemma

I have been in this situation before. It is often the case that a lot of template functions/classes in your headers are really "implementation", although by the nature of templates in C++ you are forced to put them in a header file. Thus, I just put everything in some "detail" or "implementation" namespace, where I can comfortably use "using namespace". At the end, I "drop" what people should use to the corresponding place. Like this:

namespace myproject { namespace somemodule {

namespace _implementation {

using namespace myproject::othermodule;
using namespace myproject::yetanothermodule;

template <...>
class some_internal_metafunction{
...
};

template <...>
class stuff_people_should_use_outside {
...
};

} // namespace implementation

using stuff_people_should_use_outside ;
}} // namespace myproject::somemodule

This approach might enlarge a bit the names on your compiler reports, though.

Alternatively, you can give up the modules namespaces. But it might not be a good idea for an extremely large project.

How to properly use namespaces to avoid name collision?

Of course, when I use it, I wouldn't like to type my::vector all the time, so I'd like using namespace my. However, I could eventually need something from the std namespace, and then I want using namespace std at the same time, but this will bring me back to the initial name collision problem.

Yes, it would bring you back to the initial name collision problem. This is why you should use using namespace ...; directives sparingly, and only in source files, never in headers.

Does this mean that even when I use namespaces I should still think about giving non-common names to my types?

No, you shouldn't. Namespaces were invented precisely to avoid this.

Or is using namespace a mistake and I should always type my::vector instead?

You can, if you want to, use the using namespace ...; or using ...; directives until you get conflicts. This means that when you do have conflicts, you'll end up writing "unnatural" code by explicitly quallifying names in some places.

In practice, when you're dealing with short namespace names (i.e. std), you can just type them explicitly all the time. After a week or so, you won't even notice you're typing it anymore.

c++17 namespaces, is it possible to force qualified access ALWAYS?

A) is there any way to prevent all objects in a namespace to be blind to its fellow constituents, and to require access always through :: ?

There isn't.

B) if not, what would be the correct coding practice to obtain the desired behavior?

Use a class.

C) if not, an alternative solution would be to separate the aaa namespace into 2, one for functions and another for variables, like f_aaa and v_aaa. but this seems quite clunky and ugly in practical use, eg. void f_sqlite::myfun() { v_sqlite::myvar; } instead of just void sqlite::myfun() { sqlite::myvar; }

Use a class to group relevant functions and data together. What You want to hide put in a private section.

Separate class for a namespace advisable?

You seem confused about how namespaces are used. Here are some things to keep in mind when working with namespaces:

  • You create a namespace using the syntax namespace identifier { /* stuff */ }. Everything between the { } will be in this namespace.
  • You cannot create a namespace inside a user-defined type or function.
  • A namespace is an open group construct. This means you can add more stuff into this namespace later on in some other piece of code.
  • Namespaces aren't declared unlike some of the other language constructs.
  • If you want certain classes and/or functions inside a namespace scope, enclose it with the namespace syntax in the header of where it's defined. Modules using those classes will see the namespace when the headers get #include'd.

For example, in your Entity.h you might do:

// Entity.h
#pragma once

namespace EntityModule{
class Entity
{
public:
Entity();
~Entity();
// more Entity stuff
};

struct EntityFactory
{
static Entity* Create(int entity_id);
};

}

inside your main.cpp you access it like this:

#include "Entity.h"

int main()
{
EntityModule::Entity *e = EntityModule::EntityFactory::Create(42);
}

If you also want Player to be inside this namespace then just surround that with namespace EntityModule too:

// Player.h
#pragma once
#include "Entity.h"

namespace EntityModule{
class Player : public Entity
{
// stuff stuff stuff
};
}

This works because of point #3 above.

If for some reason you feel you need to create a namespace inside a class, you can simulate this to an extent using nested classes:

class Entity
{
public:
struct InnerEntity
{
static void inner_stuff();
static int more_inner_stuff;
private:
InnerEntity();
InnerEntity(const InnerEntity &);
};
// stuff stuff stuff
};

Some important differences and caveats doing it this way though:

  • Everything is qualified with static to indicate there's no specific instance associated.
  • Can be passed as a template parameter.
  • Requires a ; at the end.
  • You can't create a convenient shorthand with abusing namespace Entity::InnerEntity;. But perhaps this is a good thing.
  • Unlike namespaces, class and struct are closed constructs. That means you cannot extend what members it contains once defined. Doing so will cause a multiple definition error.


Related Topics



Leave a reply



Submit