Reputation: 938
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).
Upvotes: 8
Views: 1149
Reputation: 12777
No, it is not possible. The only way to define a namespace is using the namespace
keyword in combination with curly braces.
7.3.1 Namespace definition [namespace.def]
1 The grammar for a namespace-definition is
namespace-name: original-namespace-name namespace-alias original-namespace-name: identifier namespace-definition: named-namespace-definition unnamed-namespace-definition named-namespace-definition: original-namespace-definition extension-namespace-definition original-namespace-definition: inlineopt namespace identifier { namespace-body } extension-namespace-definition: inlineopt namespace original-namespace-name { namespace-body } unnamed-namespace-definition: inlineopt namespace { namespace-body } namespace-body: declaration-seqopt
You can define namespace's members outside the namespace, although it must have been declared inside the namespace
(emphasis mine):
7.3.1.2 Namespace member definitions [namespace.memdef]
2 Members of a named namespace can also be defined outside that namespace by explicit qualification (3.4.3.2) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration’s namespace.
When you write
namespace name {
namespace space {
class ClassName;
}
}
you are not declaring a class ClassName
into the namespace space
, you are just providing a forward declaration.
Upvotes: 1
Reputation: 96
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...
Upvotes: 6
Reputation: 36627
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.
Upvotes: 2
Reputation: 92381
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
}
}}
Upvotes: 6