19

When using nested namespaces sometimes fully qualified names end up being quite long. I know I can use namespace abc = aaa::bbb::ccc for reducing the amount of typing (it may also improve readability in some cases).

I am not sure, however, what is the best way to achieve this renaming across all the files in a project. The straightforward approach (i.e., to rename long namespaces in a per-use basis) might lead to end up using different short names for the same fully qualified name in different files. So, I was thinking to come up with a more consistent way to do this.

For instance, let's assume something like:

project
  |- client
  |   |- core
  |   |- plugin
  |   |- util
  |- server
      ...

I was thinking to create one header per directory including the reduced names. For instance, project/client/core/core.h would contain namespace pr_cl_core = project::client::core (I know the example for this short name is rather poor, but in real projects they make more sense). Then, I would include core.h into all the header files in project/client/core so that when a header from that directory is included in, let's say, project/client/plugin/plugin_foo.h, the short namespace versions are readily available.

Is this a good approach to do so? Is there any other better way?

I have found several questions on C++ namespaces on SO (for instance, 1 and 2), but none of them relates to how to solve namespace renaming in a project-wide manner.

EDIT: Additionally, such a mechanism could be used to systematically rename long namespaces (such as Boost's ones) for a whole project. For instance, I typically rename some namespaces like:

namespace ip = boost::asio::ip;
namespace ptime = boost::posix_time;

Currently I do this on a per translation-unit basis, but I would like to do it using a global approach for the whole project.

Community
  • 1
  • 1
betabandido
  • 18,946
  • 11
  • 62
  • 76
  • You could do that, or you could make it even simpler: Have a header in the top level that declares prototypes for all of the namespaces, and the aliases. Then just include that in the subdirs. – Linuxios Jul 05 '12 at 15:55
  • @Linuxios I was thinking something like that too, but thay may end up introducing lots of dependencies: if I changed that global file, virtually all the files in the project would need to be recompiled. That being said, if the structure of namespaces does not change too much, it should not be a major problem. – betabandido Jul 05 '12 at 15:59
  • @betabendido: Ah. What about the quick and dirty solution? Preprocessor macros! Just declare them in each file for it's aliases. That way, each file can have it's own aliases. Yes, people wil yell foul for the duplication of code, but you could always add a build time script to do it for you... – Linuxios Jul 05 '12 at 16:01
  • Why use nested namespaces in the first place? Most of the SO answers for C++ namespaces basically state that namespaces are primarily to prevent collisions. They aren't well suited for nesting unlike java and c# namespaces. – NtscCobalt Jul 05 '12 at 16:02
  • @NtscCobalt Well, that could work, but in the end the problem of long namespace names is not only related to C++. The same problem could happen in other languages. And we also have Boost as a C++ example with nested namespaces :) – betabandido Jul 05 '12 at 16:10
  • 20
    @close-voters I cannot understand why this question is not constructive. At some point, SO may become a place where only questions with short and clear answers (such as "you forgot a semicolon") are allowed. I hope that never happens, though. – betabandido Jul 05 '12 at 16:13
  • 8
    The bit I am missing is, if you are willing to provide a short name for each one of the long namespaces, why don't you do that in the first place? (i.e. why have a complex namespace hierarchy and a remapped flat list)? I only consider aliased namespaces useful withing a single translation unit (i.e. in the .cpp, not the header). – David Rodríguez - dribeas Jul 05 '12 at 16:17
  • @DavidRodríguez-dribeas That's a good point. And I was actually considering that. I have actually not made my mind about it. Probably, the idea would be to just remap the most complex nested namespaces (or the ones I used the most). That means, the ones that I would manually rename them anyway. The reason to include the short versions in headers, was to reduce verbosity, especially when I need to use those long namespaces as parameters for templates. But you might be right, and it might be just better to use short names in the source files. – betabandido Jul 05 '12 at 16:27
  • 1
    @betabandido: It's not a matter of short/long answer, it's a matter of objective answers. This question is extremely subjective. Some people (like I do) will prefer `pcc` over such an unwieldy name as `pr_cl_core` for example, or just `using project::client::core::OneClass;` while others will argue over the best way of sampling the names (hungarian going ?). Therefore this question is too much up to debate to be constructive. – Matthieu M. Jul 05 '12 at 18:26
  • 1
    @MatthieuM. Well, I was not asking which naming is better (`pcc` vs. `pr_cl_core`), but how to technically implement such a renaming across a whole project. That is not subjective. There might be several solutions, but it is a clear goal, IMO. – betabandido Jul 06 '12 at 08:10
  • @betabandido: And then question becomes: why do you need it to be consistent ? As David said, most of the times the aliases we introduce are specific to the scope in which they are needed, which is why they are short. I routinely do things like `typedef std::vector> V;` for example. – Matthieu M. Jul 06 '12 at 08:24
  • 1
    @MatthieuM. I would say that many people would agree on the benefit of having consistent naming for a whole project. I cannot understand why you would want the opposite. – betabandido Jul 06 '12 at 08:43
  • @betabandido: because to be consistent and avoid name clashes, you end up with long names... which is the original problem. You are starting from `project::client::core` and reducing it to `prjct::clnt::cr` (hungarian way) or `pr_cl_core` or whatever because you *want* to avoid clashes. However if it is local, then just `pcc` works! `project::client::core` is already unambiguous, why do you want to add a long abbreviation (sic!) when having a local short-hand is all you need ? And the benefit of the short-hand is that its definition is right next to its use, which is why you can make it short! – Matthieu M. Jul 06 '12 at 12:26

1 Answers1

1

I would argue that if you repeatedly have to type long namespace names, then something is wrong in your namespace hierarchy.

Suppose you would have the same with classes, repeatedly finding yourself typing obj->sub()->subsub()->some_method(). This would be a violation of the Law of Demeter. In the case of classes, you would refactor your code (by writing wrapper functions) so that classes down in the hierarchy only have to access methods one level up.

The same should be done with namespaces: if you have to call project::client::core then you should write wrapper functions/classes in client to expose the necessary interfaces to project. If you need to do this all over the place, why not flatten your namespace structure so that client and core are at the same level?

The fact that Boost uses nested namespace is only partly true, because most of the nested namespaces like aux and detail are not supposed to be called by clients. E.g. Boost.MPL is a really good example of a library that is careful not to gratuitously expose nested namespaces.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Let's assume I decide to flatten the namespace, so I get rid of that problem. How would I solve the problem of long namespaces from Boost? I would like to avoid typing `boost::asio::ip::tcp::socket` (or similar stuff). – betabandido Jul 06 '12 at 11:58
  • @betabandido Boost.Asio indeed has overly long namespace naming. You can at least try to isolate some of that with aliases: `namespace asio = boost::asio;` and in low-level code that use TCP/IP sockets you could do `namespace socket = bost:asio::ip::tcp::socket;` e.g. – TemplateRex Jul 06 '12 at 12:13
  • That is actually what I am doing right now. But my question is how to do that renaming in a systematic way across all source files in a project. At least there are two potential advantages of doing that in a systematic way: 1) reduced amount of typing (especially if there are multiple renamings) and 2) a consistent renaming across the whole project. – betabandido Jul 06 '12 at 12:22
  • @betabandido Apart from aliasing, typedefs and refactoring your hierarchy, I think you might have to rely on your editor to do syntax-completion (Intellisense is quite OK these days). – TemplateRex Jul 06 '12 at 12:30