My library uses several nested namespaces, laid out like the following:
Library name
Class name 1
Class name 2
Class name 3
[...]
Utilities
Class name 1
[...]
Class name 2
[...]
Class name 3
[...]
[...]
The "Utilities" namespace contains useful extensions to each of the classes that don't warrant being included in the actual class itself.
The "Library name" namespace is necessary because it avoids broad conflicts with other libraries, the "Utilities" namespace is necessary to avoid the type of ambiguity that arises from things like this, and the "Class name" namespaces inside it avoid name clashes between utilities written for similar classes.
Despite this, it's still an enormous hassle in practice. Take the following, for example:
MyLibrary::MyContainer<int> Numbers = MyLibrary::Utilities::MyContainer::Insert(OtherContainer, 123, 456);
// Oh God, my eyes...
This makes me think I'm doing something seriously wrong. Is there an easier way to keep things organized, intuitive and unambiguous?
Look at how the standard library (or boost) is organized. Nearly all of it is inside the single std namespace. There's just little to be gained by putting everything inside its own namespace.
Boost puts most things inside boost, while major libraries get a single subnamespace (boost::mpl, or boost::filesystem, for example). And libraries commonly define a single aux subnamespace for internal implementation details.
But you don't typically see deep or fine-grained namespace hierarchies, because they're just painful to work with, and there's little to no benefit from them.
Here are some good rules of thumb:
Helper functions related to a specific class should be in the same namespace as the class, to enable ADL to work. Then you don't need to qualify the name of the helper function at all when calling it. (Like how you can call sort instead of std::sort on iterators defined in std).
For everything else, remember that the purpose of namespaces is to avoid name clashes and not much else. So all your library should be in a namespace, to avoid clashes with user code, but within that namespace, there's no technical need for further subnamespaces unless you plan to introduce clashing names.
You may want to separate internals of your library into a sub-namespace, so users don't accidentally pick them up from the main namespace, similar to Boost's aux.
But generally, I'd suggest as few nested namespaces as possible.
And finally, I tend to make a point of using short, easy-to-type and easy-to-read names for my namespaces (again, std is a good example to follow. Short and to the point, and nearly always without further nested namespaces, so you don't get a cramp from having to write it often, and so it doesn't clutter your source code too much.)
Just the first rule about helper functions and ADL would allow your example to be rewritten like this instead:
MyLibrary::MyContainer<int> Numbers = Insert(OtherContainer, 123, 456);
Then we could rename MyLibrary to, say, Lib:
Lib::MyContainer<int> Numbers = Insert(OtherContainer, 123, 456);
and you're down to something pretty manageable.
There shouldn't be any clashes between similar utility functions for different classes. C++ allows you to overload functions, and specialize templates, so that you can have both an Insert(ContainerA) and Insert(ContainerB) in the same namespace.
And of course, clashes between namespaces and classes are only possible if you actually have additional nested namespaces.
Remember that within your Library namespace, you alone dictate which names are introduced. And so you can avoid name clashes just by, well, not creating any clashing names. A namespace to separate user code from library code is important because the two may not know about each others, and so clashes can occur unintentionally.
But within your library, you can just give everything non-clashing names.
If something hurts, stop doing it. There is absolutely no need to use deeply nested namespaces in C++ - they are not intended to be architectural devices. My own code always uses a single level of namespaces.
If you insist on using nested namespaces, you can always create short aliases for them:
namespace Util = Library::Utility;
then:
int x = Util::somefunc(); // calls Library::Utility::somefunc()
A declaration in a header file necessitates the namespacing to not pollute the global namespace:
MyLibrary::Utilities::MyContainer<int> Numbers;
But in the source file you can use usings:
using namespace MyLibrary::Utilities;
...
MyContainer<int> Numbers;
Numbers.Insert(OtherContainer, 123, 456);
The fully qualified name doesn't actually look that bad to me, but I like being explicit in method and class names. But using can help things out:
You could probably get away with a using namespace MyLibrary at global scope in your source files, making it:
MyContainer<int> Numbers = Utilities::MyContainer::Insert(OtherContainer, 123, 456);
And then you can import the specific functions you need:
using MyLibrary::Utilities::MyContainer::Insert
and then
MyContainer<int> Numbers = Insert(OtherContainer, 123, 456);
Related
I got some confusion in mind between what my professor told us at uni and what I have read in Stroustrup's book.
We all know that a C++ header is basically a collection of
declarations (defined in a file.h) and they can contain for example a
collection of classes. They are very useful because they give us a
lot of features stored in a single space
A namespace is someting invented to organize classes, functions,
types (...) in a part of the program without defining a type.
I cannot see the concrete difference here when I have to create a project.
If I had (for example) to make a program that solves equations of various degrees, I'd put the classes that I need in a single file. For example I am going to place in equations.h all this stuff: class secondDeg, class thirdDeg, class fourthDeg and so on.
Why should I use a namespace then?
The answer (I guess) is: because you can give a name for a better organization (see std::cin). But in this case I should
Create equations.h (or whatever)
Create a namespace called eq for example
Put my classes in the namespace
Is this really necassary? Cannot I only use a header file and put all my classes inside?
Why should I use a namespace then?
A namespace can encompass multiple headers, eg., namespace std encompasses definitions from <vector> <list> etc.
You can define your own namespace to not pollute the global namespace and avoid conflicts. It's good practice to limit the namespace to the minimum for what you need, therefore using namespace std; is generally avoided.
Is this really necassary?
It depends. The better and more clear option would be to embed your declarations in a namespace.
Cannot I only use a header file and put all my classes inside?
Sure you can, just avoid any clashes with symbols declared in the global (::) scope and refrain from using namespace <xxx>; in header files.
You seem to be conflating two distinct concepts. A header is a file, typically used to contain declarations. It can contain function declarations, classes, templates, etc.
A namespace is a means of defining a scope, within which all items declared are unique. This allows you to use function and class names that might otherwise clash with names in the standard. For example
namespace mystuff
{
class list { };
};
Your list will not conflict with std::list.
Namespaces can and should be used in header files to declare the classes and such that are part of that namespace. However, as noted by others, using a 'using' directive in a header file is discouraged because it can create the very name conflicts the namespace was intended to solve.
In Java, I find it very straightforward to use namespaces. For each qualified identifier Ident I use in a source file, I put an import ns1.ns2.ns2.ns3.ns4.Ident; at the top of the file. Then I can use (short) unqualified names everywhere in my source code. The import statement cannot cause any problems, because it applies only to the file in which it is written down.
However, I'm not quite sure how to get rid of namespace qualifiers in C++ the best way.
The most obivous solution would probably be the using and using namespace statement. However, that seems to be a rather bad solution, at least in the case of header files, because the using statements are not restricted to the single file where they are written down. So using is ruled out in the case of e.g. slim libraries consisting only of header files with the implementions directly inside or in the case of header files in general.
Another option, which I use so far, is to add for each qualified name I use in a class a corresponding typedef in the private section of the class. So when comparing this approach to Java, I basically take the whole import statement list, replace the import with typedef and place it in the class declaration.
However, I don't really like this approach, because users of my classes - strictly speaking -don't know the types of return values and parameter values, because the types in the method declarations are private types of the corresponding classes.
OK, now we could make all this typedef stuff public. But that's probably a not so good idea, as we would redefine each type many many times. Just think of a struct ns1::ns2::ns3::MyStructure and two Classes MyClassA and MyClassB. Both classes have a method which actually should take as parameter an instance of ns1::ns2::ns3::MyStructure. But because every class redefines the types it uses to get rid of the long qualified names, the two methods now take parameters of "different" types, say MyClassA::MyStructure and MyClassB::MyStructure. It becomes even catchier when we have a third class MyClassC which works with an instance of MyStructure and need to call both methods with it. Should this class declare this instance with type MyClassA::MyStructure, MyClassB::MyStructure or MyClassC::MyStructure?
Well, what I simply want to know is: What is the best practise for getting rid of the namespace qualifiers?
Currently I'm working on the project that is just born. Previous developers used to name each class prepending a shorten vendor name i.e. CssMainWindow. (Css stands for Cool Software Solutions).
My question is: Shouldn't namespaces be used here? Then names of classes become much nicer.
That is:
namespace Css {
class MainWindow {
//...
};
}
What are the (ad|dis)vantages of both methods?
Appending a prefix makes the class name longer and it takes longer to type. That's the only disadvantage I can think of.
Using namespaces.... well you can just put
using namespace Css;
at the beginning of your files and file origin will be lost along with that.
I guess in the end it's up to the developer. There are 2 reasons I can think of why someone would want to identify classes:
1) For a sense of ownership. In that case, appending a prefix is, IMO, the way to go. People using your code will know it's YOUR code :).
2) For grouping classes together - in which case a namespace makes more sense.
It would depend. If your vendor-specific classes include some things like e.g.
tuple, make_tuple
string, vector
you may well wish to prefix, so as to prevent ugly ADL clashes1, and general inconvenience when people are expected to be using using namespace XXX. Popular libraries already have used that strategy (XString (Xalan), QString (Qt), CString (MFC) etc)
1 What are the pitfalls of ADL?
My suggestion: Always use namespace!
I will show several advantages of namespace:
// MainWindow.h
namespace Css {
class MainWindow {
// ...
};
};
// Other.cpp
namespace Css {
// An advantage is you don't always need to write the namespace explicitly.
MainWindow* window; // Not Css::MainWindow or CssMainWindow.
}
// In some cpp files
using namespace Css; // Never do this in header file or it will cause name pollution.
MainWindow* window; // You don't need to write Css:: in the whole file.
I can't recall any disadvantage of using namespace.
First things first.
Whatever the final choice, you should avoid as much as possible writing anything in the global namespace. You risk to face name clashes there. Therefore, your software should always be in a namespace of its own, and it's better if the name differs from those used in the libraries you depend of (reminder std is reserved already).
Once you have this namespace, then you normally don't need prefixing any longer. At least, not with the project name.
However it is mostly a matter of taste, and I have seen argued in the past that it made it easier to immediately identify where the class came from in the absence of IDE... I personally consider it and outdated habit inherited from C.
I have few questions (keeping C/C++ in context)
- When I want to use namespace?
- When I want to use classes inside namespace?
- When I should use functions/routines inside namespace (not inside class)?
Thanks.
When I want to use namespace?
You should use a namespace whenever it helps to organize your code better. You can group related classes, functions, constants, and types together under a single namespace.
When I should use functions/routines inside namespace (not inside class)?
Whenever the function does not need to be a member function. Namely, if a function does not need to access any member variables of any class instance, it should be implemented as a non-member function.
Herb Sutter's Guru of the Week articles What's In a Class? -- The Interface Principle and Namespaces and the Interface Principle discuss the use of non-member functions and namespaces in an interface.
Namespaces provides a way to organize your code, which it is useful for. Namespaces does not provide any extra functionality to C++. If used poorly it tends to the code more complicated to debug. If you decide to use namespaces, try avoid putting "using namespace" in your source files. Never use them in your header files. Point out specific classes instead "using std::vector" or similar, or add the use of "using namespace" inside a scope. This will make all your future use of namespaces much less painful.
On the project we are trying to reach an agreement on the namespace usage.
We decided that the first level will be "productName" and the second is "moduleName".
productName::moduleName
Now if the module is kind of utility module there is no problem to add third namespace. For example to add "str": productName::utilityModuleName::str - to divide space where all "strings" related stuff will go.
If the module is the main business module we have many opportunities and almost no agreement.
For example
class productName::mainModuleName::DomainObject
and
class productName::mainModuleName::DomainObjectSomethingElseViewForExample
can be both at
namespace productName::mainModuleName::domainObject
class Data
class ViewForExample
Why should we create inner not private classes and not namespaces?
Why should we create class where all methods are static (except cases when this class is going to be template parameter)?
Project consist of 1Gb of source code.
So, what is the best practice to divide modules on namespaces in the c++?
What namespaces are for:
Namespaces are meant to establish context only so you don't have naming confilcts.
General rules:
Specifying too much context is not needed and will cause more inconvenience than it is worth.
So you want to use your best judgment, but still follow these 2 rules:
Don't be too general when using namespaces
Don't be too specific when using namespaces
I would not be so strict about how to use namespace names, and to simply use namespaces based on a related group of code.
Why namespaces that are too general are not helpful:
The problem with dividing the namespace starting with the product name, is that you will often have a component of code, or some base library that is common to multiple products.
You also will not be using Product2 namespaces inside Product1, so explicitly specifying it is pointless. If you were including Product2's files inside Product1, then is this naming conversion still useful?
Why namespaces that are too specific are not helpful:
When you have namespaces that are too specific, the line between these distinct namespaces start to blur. You start using the namespaces inside each other back and forth. At this time it's better to generalize the common code together under the same namespace.
Classes with all static vs templates:
"Why should we create inner not
private classes and not namespaces?
Why should we create classes where all
methods are static"
Some differences:
Namespaces can be implied by using the using keyword
Namespaces can be aliased, classes are types and can be typedef'ed
Namespaces can be added to; you can add functionality to it at any time and add to it directly
Classes cannot be added to without making a new derived class
Namespaces can have forward declarations
With classes you can have private members and protected members
Classes can be used with templates
Exactly how to divide:
"Project consist of 1Gb of source
code. So, what is the best practice to
divide modules on namespaces in the
c++?"
It's too subjective to say exactly how to divide your code without the exact source code. Dividing based on the modules though sounds logical, just not the whole product.
This is all subjective, but I would hesitate to go more than 3 levels deep. It just gets too unwieldy at some point. So unless your code base is very, very large, I would keep it pretty shallow.
We divide our code into subsystems, and have a namespace for each subsystem. Utility things would go into their own namespace if indeed they are reusable across subsystems.
It seems to me that you are trying to use namespaces as a design tool. They are not intended for that, they are intended to prevent name clashes. If you don't have the clashes, you don't need the namespaces.
I divide namespaces depending on its usages:
I have a separate namespace, where I have defined all my interfaces (pure virtual classes).
I have a separate namespace, where I have defined my library classes (like db library, processing library).
And I have a separate namespace, where I have my core business (business logic) objects (like purchase_order, etc).
I guess, its about defining it in a way, that doesn't becomes difficult to handle in the future. So, you can check the difficulties that will surround on your current design.
And if you think they are fine, you should go with it.