In a C++ implementation file, I have the option to write something like:
name::space::ClassName::someFunction(int param) {
// impl
}
instead of
namespace name {
namespace space {
ClassName::someFunction(int param) {
// impl
}
}
}
which I find very convenient and more readable. Can this somehow be used in header files, too? Something like this:
class name::space::ClassName {
// declarations
};
instead of
namespace name {
namespace space {
class ClassName {
// declarations
};
}
}
If something like this is possible, then under which conditions? I could imagine, that one would need to forward declare the namespace forward declare the classes within the namespace like this:
namespace name {
namespace space {
class ClassName;
}
}
before being able to use this:
class name::space::ClassName {
// declarations
};
in a header file.
But somehow I am not able to get this to work 1]. Is it even possible? What bothers me is, that with nested namespaces I have to indent 2 tabs until I can actually declare my class. I would like to use that space in my header files, but I don't want to omit the tabs since this would be against the "everything in curly brackets needs to be tabbed once"-rule (I don't know if there is an actual name for this. If there is, excuse my ignorance, I don't know any :S
1] The problem I faced was not related to the question. The approach actually works, but it has drawbacks (see accepted answer).
Code in header files should always use the fully qualified namespace name.
The 'using namespace' directive pulls an entire namespace into not only your header, but also any client code that uses your header. This can provoke ambiguities in client code, or even select the wrong function during overload resolution.
A header file is a file that is intended to be included by source files. They typically contain declarations of certain classes and functions. A namespace enables code to categorize identifiers. That is, classes, functions, etc.
Since you can't put a namespace using statement at the top level of the header file, you must use a fully qualified name for Standard Library classes or objects in the header file. Thus, expect to see and write lots of std::string, std::cout, std::ostream, etc. in header files.
If you simply don't want the namespace braces enveloping your class definition, you can certainly achieve that by defining the namespace somewhere else with just the class declaration inside. That way, you can come up with something like this:
#ifndef MYCLASS_H
#define MYCLASS_H
namespace ClassNamespace { class MyClass; };
class ClassNamespace::MyClass
{
public:
MyClass();
~MyClass();
void a();
private:
};
#endif // MYCLASS_H
for the header and this:
#include "MyClass.h"
#include <iostream>
using namespace std;
ClassNamespace::MyClass::MyClass()
{
}
ClassNamespace::MyClass::~MyClass()
{
}
void ClassNamespace::MyClass::a()
{
cout << "hello";
}
for the implementation.
As you can see, the namespace doesn't enclose the class definition, just its declaration.
As a final note, I personally don't know why you'd want to do this or think it looks nicer to read. I'd personally much rather see the namespace encapsulate the class definition as well as the function definitions. But maybe I've been the odd one all along...
No, it doesn't work. One problem is that with
namespace name {
namespace space {
class ClassName {
// declarations
}
}
}
you can tell that it is two namespaces and one class.
However, with
class name::space::ClassName {
// declarations
}
you cannot tell if space
is a namespace or a class containing a nested ClassName
.
What you can do is save on your tabbing. It is possible to write
namespace name { namespace space {
class ClassName {
// declarations
}
}}
What you are seeking does not work.
One explanation is that all C++ class
and struct
types are implicitly associated with their own namespace (which has the same name as the class).
So, given
class name::space::ClassName
{
// declarations
};
the compiler has no way to determine whether name
and space
are actually namespaces or classes (at best, it must conclude that the construct is ambiguous). So the compiler needs to be explicitly told that name
is a namespace, that space
is a namespace within name
, before being told that ClassName
is a class within them.
Hence the need for
namespace name
{
namespace space
{
class ClassName;
}
}
to forward specify both namespaces and forward declare ClassName
within them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With