Using a classes within multiple namespaces across multiple files in C++ - c++

I'm having a problem compiling the following code with avr-g++ (C++ compiler for AVR micro-controllers).
#ifndef SPI_H_
#define SPI_H_
#include "../LIBcpp.hpp"
namespace uC
{
namespace SPI
{
class Device
{
private:
SPI* m_SPI;
uC::IO::Pin* m_CSPin;
ChipSelectPolarity m_CSPolarity;
public:
Device(SPI& _SPI, uC::IO::Pin& _CSPin, ChipSelectPolarity _CSPolarity);
void Select();
void DeSelect();
void WriteByte(uint8_t _Data);
uint8_t WriteReadByte(uint8_t _Data);
void WriteBytes(uint8_t _Data[], uint8_t _DataLength);
void WriteReadBytes(uint8_t _Data[], uint8_t _ReadBuffer[], uint8_t _DataLength);
};
}
}
#endif /* SPI_H_ */
Note that I have defined several enumerations and classes within this file that are used in this class but have not been included to prevent the code from being too long.
I receive the errors
'IO' in namespace 'uC' does not name a type
'uC::IO' has not been declared
expected ',' or '...' before '&' token
In my project, I have several files that represent specific modules of the project that I am working on. These files are in a sub-directory named Modules. The header file LIBcpp.hpp is in the directory above that. It includes the all of the header files within the Modules sub-directory.
The class Pin is defined within the namespace IO, which is within the namespace uC. This class is defined in a header file named IO.hpp, which is included by LIBcpp.hpp.
What I have tried:
Including the IO.hpp header file in the SPI.hpp header file - resulting in the same errors
I am at a loss as to how to solve this error. If more code or information is required to solve this problem, I will provide it.
Thanks!
This is IO.hpp, as requested:
#ifndef IO_H_
#define IO_H_
#include "../LIBcpp.hpp"
namespace uC
{
namespace IO
{
class Port
{
//Contents removed
};
class Pin
{
//Contents removed
};
}
}
#endif /* IO_H_ */

The class "Pin" is defined within the namespace "IO", which is within
the namespace "uC". This class is defined in a header file named
"IO.hpp", which is included by "LIBcpp.hpp".
But IO.hpp includes LIBcpp.hpp. You have circular inclusions- this is extremely bad. You must alter your header structure so that there are no circular inclusions.

Related

Is it possible to add an include directive inside of a class definition?

I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.

Is it safe to separate your templated class' declaration and definitions on different header files?

I'm trying to create a library for a school work, and I've been wondering if it is safe to declare a templated class on the main header file containing the class definition and method declarations, but then separating the method definitions in a different header file?
Because I have been able to do this in my example below, but I don't know if it will cause me some problems in the long run.
main program
// main.cpp
#include <iostream>
#include "declaration.hpp"
int main()
{
card<int> a(5);
std::cout<<a.getID()<<'\n';
return 0;
}
main header file
in this header file, only the class definition and the declaration of the method getID() is written but not it's definition, and by the end of the class I included the other header file that contains the method definitions.
// declaration.hpp
#ifndef DEC_HPP
#define DEC_HPP
#include <iostream>
template<typename T>
class card
{
public:
T id;
card(const int id) : id(id) {}
T getID();
};
#include "definition.hpp"
#endif
method definitions
This header file contains the method definition of getID() from the main header.
I also included the "declaration.hpp" in this header, and this is the part where I'm not so sure of, because I included both files together with each other.
// definitions.hpp
#ifndef DEF_HPP
#define DEF_HPP
#include <iostream>
#include "declaration.hpp"
template<typename T>
T card<T>::getID()
{
return id;
}
#endif
I have compiled this program and it's working on my machine, but I just wanted to know if this way of isolating my code will cause me some errors in the future, I don't want to put my templated class definitions in a cpp files because I find it hard to maintain.
This is indeed a better approach because it makes your code look simple and better. Moreover, it is the main reason why header file is used.
Your main header file will simply tell that what functions/classes are you using and without even viewing your code, anyone can guess if you are working correctly or not.
There wont be any safety issues at all.

Duplicate Symbol in nested namespace

I am working on a library that I'm using in my other projects and I have the following header file:
#pragma once
#include <iostream>
#include <map>
#include "my_library/core/Structures.h"
namespace My_Library
{
namespace NodeReaders
{
namespace HumanReadable
{
char charBuffer[256];
unsigned int uintBuffer;
unsigned long long microsecondBuffer;
unsigned int getNextUInt(std::istream & is)
{
/// Implementation
}
unsigned long getNextMicroseconds(std::istream & is)
{
/// Implementation
}
...
}; // namespace HumanReadable
}; // namespace NodeReaders
}; // namespace My_Library
I've tried to include it in a couple of different source files, but whenever I do, I get an error that there is a duplicate symbol for each of the used functions defined here. Why am I getting a duplicate symbol error? Isn't #pragma once supposed to make it so that that doesn't happen?
Edit: Snippit of error message:
duplicate symbol __ZN8My_Library11NodeReaders13HumanReadable10uintBufferE in:
obj/project/Debug/ParseDriver.o
obj/project/Debug/ParseService.o
#pragma once makes sure the header file is only included once in each translation unit it's included in. So if you include it in more than one cpp file, you will get multiple implementations.
Declare your functions inline e.g. :
inline unsigned int getNextUInt(std::istream &is)
{
...
}
Or, put the function implementations in a cpp file.
The variables have to be defined in a cpp file. In the header file, you will have this:
extern unsigned int uintBuffer;
and in the cpp file you have this:
unsigned int uintBuffer;
All of this becomes easier when you use classes instead of global variables and functions.

struct in separate header file causing problems in C++

I have a struct Tree that is defined inside Class Parser. I have methods defined in Parser that take Tree as input.
void Parser::InputTree(const Tree& input) {
//uses data from Tree
}
Everything seemed to be working fine. But then I needed to use Tree outside the class. So I decided to define struct Tree in a separate header. I included this header in the header file for Parser. While I see no errors in the header file of Parser, the source file shows errors on my Eclipse. Says member declaration not found pointing to method InputTree.
My question is, first off is this the right strategy to define a struct in a separate header? Second, what am I doing wrong? Third, I have some enum types also that I want to use across classes. Where do I define it?
Right structure:
parser.h
#ifndef _PARSER_H_
#define _PARSER_H_
#include "tree.h"
class Parser {
void InputTree(const Tree& input);
};
#endif /*_PARSER_H_*/
parser.cpp
#include "parser.h"
void Parser::InputTree(const Tree& input){
// use data from Tree
}
tree.h
#ifndef _TREE_H_
#define _TREE_H_
struct Tree {
//nodes
};
#endif /*_TREE_H_*/
Including parser.h includes tree.h and hence, struct Tree is available in the main compilation unit.
A simple rule of the thumb I usually follow, is if a custom datatype (i.e. struct, enum, etc.) is used only within a class, I end up defining this datatype within the definition of the class.
But if the same type is required to be used across 2 or more classes (without any parent-child relationship), I end up defining the type either within another header file and usually within a namespace (when the types or related in some fashion).
And yes you could use multiple such namespaces within multiple header files (to group related types), if you feel the need to distinguish them, but I've just show a simpler example using a single namespace:
/* MyNamespace.h */
#ifndef MY_NAMESPACE_H
#define MY_NAMESPACE_H
namespace MyNamespace {
struct Tree {
int a;
char b;
};
enum SomeEnum {
VALUE_0 = 0,
VALUE_1 = 1,
VALUE_2 = 2
};
}
#endif
/* Parser.h */
#ifndef PARSER_H
#define PARSER_H
#include "MyNamespace.h"
class Parser
{
public:
void InputTree(const MyNamespace::Tree& input);
};
#endif
/* Parser.cpp */
#include "Parser.h"
void Parser::InputTree(const MyNamespace::Tree& input)
{
}
Yes, it is a correct strategy to define the struct in a separate header file.
What you are doing wrong is hard to say without more input - but it probably has to do with includes, include-guards or namespace mismatches.
And finally, you should declare the enums in another header file, with proper include guards.

C++ namespaces trobles

//portl.cpp
namespace FAWN {
namespace Sys{
class PortListner {
....
Connecter::ConPtr _cur_con; - the main problem is here
...
//con.cpp
namespace FAWN {
namespace Sys {
class Connecter {
.....
public:
typedef boost::shared_ptr<Connecter> ConPtr;
...
Moreover, portl.cpp file is included into some other "main" sourse file. And this "other-main" file includes con.cpp too. So if I include con.cpp to portl.cpp - I define Connecter twice (in portl and in main). If I do not include it, compilator doesn't know what Connecter::ConPtr (or FAWN::sys::Connecter::ConPtr) means and try to use it as defenition of method.
Put the class Connecter (which you should probably rename to Connector) into a header file (.h instead of .cpp) and add include guards into the file. That is, at the beginning of your con.h file, add lines
#ifndef CON_H_INCLUDED
#define CON_H_INCLUDED
and at the very end, add the line
#endif
This way, even if you #include con.h twice, the second time it will not get read because the symbol CON_H_INCLUDED has been defined on the first time so the #ifndef-#endif pair hides the content.
This is the common way in C++: put class declarations in .h files that get #included in .cpp files that then actually define the functions.
Here is how it should look:
#ifndef PORTAL_H
#define PORTAL_H
#include "con.h"
//portl.h
namespace FAWN {
namespace Sys{
class PortListner {
....
//might need to specify Connector's namespace fully here
FAWN::Sys::Connecter::ConPtr _cur_con;
...
};
}
#endif //PORTAL_H
//con.h
#ifndef CON_H
#define CON_H
namespace FAWN {
namespace Sys {
class Connecter {
.....
public:
typedef boost::shared_ptr<Connecter> ConPtr;
};
}
#endif //CON_H