c++ namespace best practice dilemma
I'm finding that what I've considered "best practice" for use namespace in c++ is hurting the readability of my code, and making me question how to use them well.
My program consists of a few different modules which are mostly built into libraries that the "main" application uses. Each library uses it's own namespace, and their namespaces are all "inside" a project namespace to help project against name conflicts with 3rd party code. So I end up with class names such as "myproject::logging::Logger" and "myproject::reporting::ReportType" (As made up examples).
So far so good. And in my .cpp files I have no problem. I use "using myproject::logging" at the top for example, and can cleanly refer to my Logging class. In the unlikely event of a conflict between two of my namespaces I can just explicitly say which one I want. This works well.
Header files are different though. It's considered bad practice to put using statements into header files as they will affect unrelated code that may not expect them. So I always fully qualify all the names in .hpp files. That was s开发者_高级运维omewhat ugly but managable up to now so I've put up with it. But now I'm increasing using template code in my libraries which means that there is much more actual code in my .hpp files now. And having to fully qualify every name is making the code practically unreadable due to the length of type names.
I'm starting to feel that the benefits of namespaces and best practice for using them are beginning to be outweighed by the unreadablilty of the code I'm having to write. I'm starting to wonder if I would be better abandoning the use of namespaces to gain the benefit of more readable code and fixing any name conflicts if and when they appear.
An alternative is to use short, single layer namespaces so instead of "myproject::logging::Logger" I would merely have "log::Logger" which would help a lot but make the likelyhood of namespace conflicts much higher, and also have the namespaces convey less useful information.
As I've said, this only really affects code in .hpp files as I'm happily using "using namespace" in my implementation files to make this manageable, but it is becoming a problem as I look at my templated code in .hpp files now and think "eww...." which can't be good :P
Anyone got any practical advice?
Here's what I do.
In <mylibrary.h>
:
namespace myproject {
namespace mylibrary
{
namespace impl
{
using namespace otherlibrary;
using namespace boost;
using namespace std;
using namespace whatever::floats::your::boat;
class myclass;
class myotherclass;
};
using impl::myclass;
using impl::myotherclass;
};
};
In the source:
#include <mylibrary.h>
using namespace myproject::mylibrary; //clean!
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.
Personally? I'd get rid of the "myproject" part. What is the chance that your library will use the exact same namespace name as another and have a symbol defined with the same name as another?
Also, I would suggest shorter names for namespaces you expect to be used in headers.
My experience have been that it is much more convenient to have one namespace for all your code for the reasons you mentioned in your original post. This namespace protects your identifiers from clashing with identifiers from 3rd-party libraries. Your namespace is your dominion and it is easy to keep it name-conflict-free.
I use the following to get rid of enormous amounts of std::
in header file:
// mylibrary.h
namespace myproject {
namespace mylibrary {
namespace impl {
using namespace std;
namespace stripped_std {
// Here goes normal structure of your program:
// classes, nested namespaces etc.
class myclass;
namespace my_inner_namespace {
...
}
} // namespace stripped_std
} // namespace impl
using namespace impl::stripped_std;
} // namespace mylibrary
} namespace myproject
// Usage in .cpp file
#include <mylibrary.h>
using namespace myproject::mylibrary;
It is similar to what was suggested by n.m., but with a modification:
there is one more auxiliary namespace stripped_std
.
The overall effect is that line using namespace myproject::mylibrary;
allows you to refer to the inner namespace structure, and at the same time it does not bring namespace std
into library user's scope.
It's a pity though that the following syntax
using namespace std {
...
}
is not valid in C++ at the time when this post is written.
If your project isn't very very very huge (I mean, very huge), using only myproject should be sufficent. If you really want to divide your project into parts, you can use more generalized namespaces. For example, if I was building a game engine, I would go for namespaces like MyEngine::Core, MyEngine::Renderer, MyEngine::Input, MyEngine::Sound etc.
精彩评论