CharlyDelta
CharlyDelta

Reputation: 938

Header files without explicitly writing namespace

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

Answers (4)

Paolo M
Paolo M

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

nicholaschiasson
nicholaschiasson

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

Peter
Peter

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

Bo Persson
Bo Persson

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

Related Questions