Should every class have its own namespace?
Something that has been troubling me for a while:
The current wisdom is that types should be kept in a namespace that only contains functions which are part of the type's non-member interface (see C++ Coding Standards Sutter and Alexandrescu or here) to prevent ADL pulling in unrelated definitions.
Does this imply that all classes must have a namespace of their own? If we assume that a class may be augmented in the future by the addition of non-member functions, then it can never be safe to put two types in the same namespace as either one of them may introduce non-member functions that could interfere with the other.
The reason I ask is that namespaces are becoming cumbersome for me. I'm writing a header-only library and I find myself using classes names such as project::component::class_name::class_name. Their implementations call helper functions but as these can't be in the same namespace they also have to be fully qualified!
Edit:
Several answers have suggested that C++ namespaces are simply a mechanism for avoiding name clashes. This is not so. In C++ functions that take a parameter are resolved using Argument Dependent Lookup. This means that when the compiler tries to find a function definition that matches the function name it will look at every function in the same namespace(s) as the type(s) of its parameter(s) when finding candidates.
This can have unintended, unpleasant consequences as detailed in A Modest Proposal: Fixing ADL. Sutter and Alexandrescu's rule states never put a function in the same namespace as a class unless it is meant to be part of the interface of that class. I don't see how I can obey that rule unless I'm prepared to give 开发者_Python百科every class its own namespace.
More suggestions very welcome!
No. I have never heard that convention. Usually each library has its own namespace, and if that library has multiple different modules (e.g. different logical units that differ in functionality), then those might have their own namespace, although one namespace per library is sufficient. Within the library or module namespace, you might use namespace detail
or an anonymous namespace to store implementation details. Using one namespace per class is, IMHO, complete overkill. I would definitely shy away from that. At the same time, I would strongly to urge you to have at least one namespace for your library and put everything within that one namespace or a sub-namespace thereof to avoid name clashes with other libraries.
To make this more concrete, allow me to use the venerable Boost C++ Libraries as an example. All of the elements within boost reside in boost::
. There are some modules within Boost, such as the interprocess library that have its own namespace such as boost::interprocess::
, but for the most part, elements of boost (especially those used very frequently and across modules) simply reside in boost::
. If you look within boost, it frequently uses boost::detail
or boost::name_of_module::detail
for storing implementation details for the given namespace. I suggest you model your namespaces in that way.
No, no and a thousand times no! Namespaces in C++ are not architectural or design elements. They are simply a mechanism for preventing name clashes. If in practice you don't have name clashes, you don't need namespaces.
To avoid ADL, you need only two namespaces: one with all your classes, and the other with all your loose functions. ADL is definitely not a good reason for every class to have its own namespace.
Now, if you want some functions to be found via ADL, you might want to make a namespace for that purpose. But it's still quite unlikely that you'd actually need a separate namespace per class to avoid ADL collisions.
Probably not. See Eric Lippert's post on the subject.
Couple things here:
- Eric Lippert is a C# designer, but what he's saying about bad hierarchical design applies here.
- A lot of what is being described in that article has to do with naming your class the same thing as a namespace in C#, but many of the same pitfalls apply to C++.
You can save on some of the typedef pain by using typedef
s but that's of course only a band-aid.
It's quite an interesting paper, but then given the authors there was a good chance it would be. However, I note that the problem concerns mostly:
typedef
, because they only introduce an alias and not a new type- templates
If I do:
namespace foo
{
class Bar;
void copy(const Bar&, Bar&, std::string);
}
And invoke it:
#include <algorithms>
#include "foo/bar.h"
int main(int argc, char* argv[])
{
Bar source; Bar dest;
std::string parameter;
copy(source, dest, parameter);
}
Then it should pick foo::copy
. In fact it will consider both foo::copy
and std::copy
but foo::copy
not being template will be given priority.
精彩评论