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).
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.
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.
Related
I remember being told that C++ classes have their own namespaces, and that the class name could be used as a namespace for scope resolution, like this:
// Example.h
class Example {
void Private();
public:
void Public();
}
and, later in a manner similar to this:
// Example.cpp
#include "Example.h"
using /*namespace*/ Example;
void Private() {}
void Public() {}
instead of:
// Example.cpp
#include "Example.h"
void Example::Private() {}
void Example::Public() {}
but I couldn't find neither an explanation nor an example of that in my books. A brief Google search was also a dead-end. Is this a real thing?
No, namespaces and classes are different.
However, namespaces and classes both introduce a scope which may be referred to using the scope resolution operator :: .
The using namespace N; declaration can only apply to namespaces. It's not possible to do something similar for a class. You can only do using Example::x; for specific names x inside Example to import them one by one.
When providing the member function body out-of-line, you must write Example::Private(), there is no alternative.
Yes, Every class has its own namespace that everything part of the class declaration belongs to.
You may employ the using directive as you indicate as explained here.
It should be noted that you cannot declare a namespace with the same name as a class as shown here:
namespace fubar
{
class snafu
{
...
};
}
// Cannot do stuff below (ERROR)
namespace fubar::snafu;
{
// this is not valid, once a class always a class
// once a namespace, always a namespace
// a class makes a namespace also but never JUST a namespace
}
Do be careful though. 'Using' too much can play real tricks on you and those who inherit your code.
I am trying to avoid including an auto-generated header (outside of my control), from inside my own headers. I therefore need to forward-declare a type Type that lives inside a namespace nm, which itself lives in the global namespace. Here is an example of MyHeader.h:
// My project defines two levels of nested namespaces
namespace foo { namespace bar {
namespace nm { struct Type; }
...
} }
Unfortunately this defines the new namespace foo::bar::nm and forward-declares the type foo::bar::nm::Type, which is not what I want. Ideally I would be able to forward-declare a type in the qualified namespace ::nm like this:
namespace foo { namespace bar {
namespace ::nm { struct Type; }
...
} }
My compiler complains I cannot use a qualified namespace here (using Intel ICC15 with C++11 settings). This forces me to put all such forward declarations at the beginning:
namespace nm { struct Type; }
namespace foo { namespace bar {
...
} }
In my case, this is inconvenient because I need to forward-declare many types and would prefer to do so alongside definitions of my own in various scattered places in my header. A workaround could be to constantly be "closing" and "re-opening" my nested namespace, which is not ideal.
Why can't I forward-declare a type in a qualified namespace ?
Because the C++ standard says so.
There is no real reason I know of. This is just not supported, probably, no one needed it and no one ever requested it. I see the benefit in your particular case, but since the forward declarations are expected to be provided in a separate file, you'd be better off by simply creating your own *_fwd.h with all the forward declarations inside it in the single namespace.
You can't because it's ambiguous. If you wrote:
extern int foo::bar;
Are you forward declaring an int named bar in namespace foo, or are you forward declaring an int named bar inside the class foo? There's no way for the compiler to know.
I write some header file. I want separately declare the namespaces hierarchy (for clarity), and and then declare functions and classes. For me it looks as a table of contents in the document. It would be very convenient for me: to see the full hierarchy of namespaces in one place. I write this:
// Namespaces hierarchy:
namespace Bushman{
namespace CAD_Calligraphy{}
//...
}
// Declarations of classes and functions
class Bushman::CAD_Calligraphy::Shp_ostream{
public:
explicit Shp_ostream(std::ostream& ost);
};
But MS Visual Studio shouts on such way of creation of the header file. I should write so:
namespace Bushman{
namespace CAD_Calligraphy{
class Shp_istream{
public:
explicit Shp_istream(std::istream& ist);
};
}
}
Why the first variant doesn't work? Is this restriction of the C++, or IDE?
P.S. My additional question is here.
Thank you.
The restriction is in §9/1: "If a class-head-name contains
a nested-name-specifier, the class-specifier shall refer to
a class that was previously declared directly in the class or
namespace to which the nested-name-specifier refers[...]". In
other words, the first appearance of the class name cannot be in
something like Bushman::CAD_Calligraphy::Shp_ostream.
What you can do is add forward declarations in your initial
declaration of the hierarchy:
// Namespaces hierarchy:
namespace Bushman{
namespace CAD_Calligraphy{
class Shp_ostream;
//...
}
//...
}
// Declarations of classes and functions
class Bushman::CAD_Calligraphy::Shp_ostream{
public:
explicit Shp_ostream(std::ostream& ost);
};
Depending on how your headers are organized, this might even be
better from the human point of view: your header starts with
a sort of index of what is defined in it.
To quote the standard: Section 7.3.1.2 point 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.
namespace Q {
namespace V
void f();
}
void V::f() { /∗ ... ∗/ } // ok.
void V::g() { /∗ ... ∗/ } // Error: g() is not yet a member of V
namespace V
void g();
}
}
namespace R {
void Q::V::g() { /∗ ... ∗/ } // // error: R doesn’t enclose Q
}
So, you could do what you have in your original post, if you declare the class name there:
namespace Bushman{
namespace CAD_Calligraphy {
class Shp_ostream;
...
}
}
That's how C++ works.
It's consistent with other nested declarations: you can't add members to a class from outside the class:
class A
{
};
void A::f() { } // Error!
And you can't add enumerators to an enum from outside:
enum E { E1 = 1, E2 = 2 };
E::E3 = 3; // Error!
You need to "open" the scope and declare the entity inside the scope. Once it's declared you can define it outside that scope, using a nested-name:
class A
{
void f(); // declare
};
void A::f() { } // define
First of all, C++ is not designed to work like that. So it is not a surprise that this is happening.
But, since you're using Visual Studio, you could take advantage of partial classes. Unfortunately, it seems this characteristic is only related to C++/CX so maybe yo won't be able to use it.
You will still need to declare a partial class in your namespace hierarchy, but I guess it could be empty.
To be honest, I haven't used this feature and I don't know how far can it be bent in order to achieve what you want. But you could anyway give it a try.
Remember that this is a Visual Studio extension, so your code won't be cross-platform.
Hope this helps. Somehow.
I usually use forward declaration predominantly, if I have a class that does not need complete definition in .hpp file
Ex)
//B.hpp
namespace A_file {
class A;
}
namespace B_file {
class B {
public:
B();
private:
A *ptr_to_A;
}
}
//B.cpp
#include "A.hpp"
using namespace A_file;
namespace B_file {
B(int value_) {
*ptr_to_A = new A(value_);
}
int some_func() {
ptr_to_A->some_func_in_A();
}
}
I write this kind of code. I think, it will save including the whole hpp again. (Feel free to comment, if you thing, this is not healthy)
Is there a way that I can do the same for objects/classes in std namespace?
If there is a way, is it okay or does it have side effects?
You can forward declare your own classes in header files to save compilation time. But you can't for classes in namespace std. According to the C++11 standard, 17.6.4.2.1:
The behavior of a C++ program is undefined if it adds declarations or
definitions to namespace std or to a namespace within namespace std
unless otherwise specified.
Note that some of these classes are typedefs of templated classes, so a simple forward declaration will not work. You can use #include<iosfwd> instead of #include<iostream> for example, but there are no similar headers with just forward declarations for string, vector, etc.
See GotW #34, Forward Declarations for more information.
What is namespace used for, in C++?
using namespace std;
Namespace is used to prevent name conflicts.
For example:
namespace foo {
class bar {
//define it
};
}
namespace baz {
class bar {
// define it
};
}
You now have two classes name bar, that are completely different and separate thanks to the namespacing.
The "using namespace" you show is so that you don't have to specify the namespace to use classes within that namespace. ie std::string becomes string.
It's used for preventing name confilct, so you may have two classes with the same name in different namespaces.
Also it's used for categorizing your classes, if you have seen the .net framework, you will see that namespaces are used for categorizing the classes. For example, you may define a namespace for the employee classes, and a namespace for the tasks classes, and both namespaces are within a namespace for the company classes, since a namespace may contain sub namespaces.
The same namespace may exist in different files, so using it may be useful because it will make you able to directly use all the classes in the namespaces in every #included file.
That's what I remember for now.
One could ask, simple pair of curly braces {} are sufficient to resolve name conflict. Still why have a NameSpace. A quick answer as Tamer mentioned above is that with NameSpace we get the ability to open the same scope in another file.
Namespace usually is used to prevent naming conflicts.
So, One place where namespace comes into picture is
class ABC{
// Does something for me.
};
class ABC{
// Does something for you..
};
int main() {
ABC myABC;
return 0;
}
This will give a compilation error as the system will not know which class is to be considered. Here the concept of namespace comes into picture.
namespace My{
class ABC{
// Does something for me.
};
}
namespace Your{
class ABC{
// Does something for you..
};
}
using My::ABC
// We explicitly mention that My ABC is to be used.
int main() {
ABC myABC;
return 0;
}
Code will be much organized with the usage of namespaces.