MISRA C++ 2008 Rule 7–3–1 and Forward Declaration - c++

Let's say I wanted to forward declare CLibraryStruct in my MyClass.hpp
class CLibraryStruct;
class MyClass {
private:
CLibraryStruct *cLibStr;
};
At the same time I also wanted to be compliant with MISRA C++ 2008 Rule 7–3–1:
The global namespace shall only contain main, namespace declarations and extern "C" declarations.
I obviously can't use anonymous namespaces here, but I think I could try this:
class MyClass {
private:
class CLibraryStruct *cLibStr;
};
Or this:
#include "CLibrary.h"
class MyClass {
private:
CLibraryStruct *cLibStr;
};
Would you be so kind as to help me out and explain to me which would be a better choice (or suggest an alternative)?

Related

Will C++17 allow forward declaration of nested classes?

Not sure where to ask (feel free to close this if it is an inappropriate question) but I have not found anything on this specifically in C++17 proposals, neither this or this mentions it when dealing with the nested namespace addition to C++.
So currently this is the only option:
class A
{
public:
class B; //forward-declared INSIDE class/namespace
};
class A::B //defined outside
{
};
Will this be possible in C++17?
class A::B; //forward declared NESTED outside of parent class/namespace
class C
{
A::B *b;
};
and then either this (1) (as seems to be the proposal of nested namepsace definitions)
class A::B //definition of A::B without defining A
{
};
or this (2)
class A
{
public:
class A::B
{
};
};
or this [3]
class A
{
public:
class B;
};
class A::B
{
};
I suspect the definition of A::B without defining A first might not work though (although the proposal seems to allow it).
There's a proposal on the issue titled Forward declarations of nested classes P0289R0. However as you can see from the last Trip Report: C++ Standards Meeting in Jacksonville, February 2016, this proposal was pendent to proposals for which further work is encouraged. I'm quoting the verdict of the committee (Emphasis Mine):
This would allow things like X::A* to appear in a header without
requiring a definition for X to also appear in the header
(forward-declarations of X and X::A will be sufficient). EWG found the
use case compelling, because currently a lot of class definitions to
appear in headers only because interfaces defined in the header use
pointers or references to nested classes of the type. Several details
still need to be worked out. (For example, what happens if a
definition of X does not appear in any other translation unit (TU)?
What happens if a definition of X appears in another TU, but does not
define a nested class A? What happens if it does define a nested class
A, but it’s private? The answer to some or all of these may have to be
“ill-formed, no diagnostic required”, because diagnosing errors of
this sort would require significant linker support.)
IMHO lacking the ability to do forward deceleration of classes is a major hole in C++ language definition, which results in people using void* where a forward reference would be more safe.
Here is a workaround using namespaces:
Flatten the class structure you need to pre-declare
Use namespaces to separate the code
Do the forward deceleration using the namespaces
namespace ns1 {
namespace ns2 {
typedef class C * cptr_t; // declare both class and a pointer type
}}
ns1::ns2::C *cp; // use forward deceleration of the class
ns1::ns2::cptr_t cp; // use the typedef
This workaround does not solve the problem properly but may help in some situations.

Can a class name be used as a namespace?

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.

Why I can't separately write namespace's hierarchy in the header file?

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.

Forward Declaration of variables/classes in std namespace

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.

C++ Namespace 'using' declarative for a class' enum

I have a good understanding of how the C++ 'using' declaration and directive work. However, I'm stumped on this... Maybe it's not possible? I want to avoid having to quality my enum variables:
namespace Foo {
class MyClass {
public:
enum MyEnum { X, Y, Z };
}
}
And now, from outside that namespace, I would like to be able to do things like:
using Foo::MyClass.MyEnum;
MyEnum letter = MyEnum::x;
But apparently that's not the way to do it? I'm betting this is possible, but my notation is wrong... I also tried using Foo::MyClass::MyEnum, but then the compiler thinks Foo::MyClass is a namespace.
Added: As you can see, it becomes annoying having to fully declare everything...
Foo::MyClass::MyEnum value = Foo::MyClass::X;
This doesn't answer your question directly, but if you want to economize keystrokes you could try using a typedef instead.
typedef Foo::MyClass::MyEnum MyClassEnum;
By the way, it looks like your question has been asked on Stack Overflow before. From the answer to that question:
A class does not define a namespace,
therefore "using" isn't applicable
here.
C++03 does not support fully qualifying enum types, but it's an MSVC extension. C++0x will make this Standard, and I believe that you can using an enum in C++0x. However, in C++03, I don't believe that your problem can be solved.
I got the following to compile, after messing around a lot. I think that it will be the closest you can get without typedef'ing.
namespace Foo {
class MyClass {
public:
enum MyEnum { X, Y, Z };
};
};
namespace Foo2 {
using Foo::MyClass;
class AnotherClass {
public:
AnotherClass(){
MyClass::MyEnum value = MyClass::X;
}
};
};
int main(){
return 1;
}
You could also use MyClass as a base class, but I am doubting that's something you want to do.
namespace Foo2 {
using namespace Foo;
class AnotherClass : public MyClass{
public:
AnotherClass(){
MyEnum value = X;
}
};
};
This also has some good info.
namespaces for enum types - best practices