C++ - Why do I have to include .cpp file along with/ instead of .h file to acces the value of a global variable in the following case? - class

I am trying to properly declare and define global variables in separate files and include them in a third file which deals with class declaration.
The three files are:
1) global.h
#ifndef GLOBAL_H_INCLUDED
#define GLOBAL_H_INCLUDED
extern const int marker_num;
extern const int dim;
using namespace std;
#endif // GLOBAL_H_INCLUDED
2) global.cpp
#include <iostream>
#include <cstdio>
#include <cmath>
#include "global.h"
#include "WorldState.h"
#include "Robot.h"
#include "Sensor.h"
#include "Marker.h"
constexpr const int marker_num = 10;
constexpr const int dim = (2 * marker_num) + 3;
3) WorldState.h
#ifndef WORLDSTATE_H
#define WORLDSTATE_H
#include "global.h"
#include "global.cpp"
class WorldState{
public:
WorldState(float a[], float b[dim][dim]);
get_wstate();
protected:
private:
float w_state[];
float covar_matrix[dim][dim];
};
#endif // WORLDSTATE_H
I am using the global variable dim to declare and define a multidimensional array. I have declared dim inside global.h and defined it inside global.cpp. Now, I have a class called WorldState and inside its header, I am using dim. If I comment out #include "global.cpp", it throws the following error:
C:\Users\syamp\Documents\codeblocks\slam\WorldState.h|10|error: array bound is not an integer constant before ']' token
My understanding is that including the .h file includes the corresponding .cpp as well, and that all declarations should be inside .h and all definitions should be inside .cpp. However, it doesn't seem to work in this case.
1) If I decide to include global.cpp file inside WorldState.h, isn't it bad programming practice? I am trying to write a good code not just a code that works.
2) An alternative is to define values of variable(s) dim (and marker_num) inside global.h. Is that good programming practice?
3) I believe there is something that I am missing. Kindly suggest the best method to resolve this issue. I am using codeblocks and C++11. Thanks in advance.

I am using the global variable dim to declare and define a multidimensional array.
When declaring a fixed-length array at compile-time, the value(s) of its dimension(s) must be known to the compiler, but your separation prevents the value of dim from being known to the compiler at all, so dim cannot be used to specify fixed array dimensions. Any code that uses dim will just compile into a reference to it, and then the linker will resolve the references after compilation is done. Just because dim is declared as const does not make it suitable as a compile-time constant. To do that, you must define its value in its declaration, eg:
#ifndef GLOBAL_H_INCLUDED
#define GLOBAL_H_INCLUDED
static constexpr const int marker_num = 10;
static constexpr const int dim = (2 * marker_num);
using namespace std;
#endif // GLOBAL_H_INCLUDED
Otherwise, if you keep dim's declaration and definition in separate files, you will have to dynamically allocate the array at run-time instead of statically at compile-time.
I have declared dim inside global.h and defined it inside global.cpp.
That is fine for values you don't need to use until run-time. That will not work for values you need to use at compile-time.
My understanding is that including the .h file includes the corresponding .cpp as well
That is not even remotely true. The project/makefile brings in the .cpp file when invoking the compiler. The .h file has nothing to do with that.
that all declarations should be inside .h and all definitions should be inside .cpp.
Typically yes, but not always.
If I decide to include global.cpp file inside WorldState.h, isn't it bad programming practice?
Yes.
An alternative is to define values of variable(s) dim (and marker_num) inside global.h. Is that good programming practice?
Yes, if you want to use them where compile-time constants are expected.

Related

Undefined reference to `ulocdata_open_63'

I am using ICU lib for Exemplar, I am getting undefined ref for `ulocdata_open_63'
I am not using "ulocdata_open_63" function but "ulocdata_open". Library is linked properly.
Why it is looking for ulocdata_open_63 definition even though I am not calling it.
Sample code:-
#include <stdio.h>
#define UNICODE
#include <unicode/uloc.h>
#include <unicode/ulocdata.h>
#include <unicode/urename.h>
typedef unsigned short U16;
int main()
{
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY] = "en_US";
UErrorCode icuStatus = U_ZERO_ERROR;
ULocaleData* uld = ulocdata_open("en", &icuStatus);
...
}
It looks you're linking against a ICU library that was built with ICU version suffixes, which is the default. To build a library without version suffixes you'll have to add the flag --disable-renaming to the configure build step of ICU4C.
See https://unicode-org.github.io/icu/userguide/icu4c/build.html#icu-as-a-system-level-library.

std::vector in MyClass ptr causing crash on destructor

I have a problem in regards to a custom class I have made. The original intention was to create a particle emitter and in this emitter are two vectors to hold colors and the particles themselves.
The problem exactly is trying to destruct this custom class which functions perfectly if you do not call the destructor, which is obviously bad.
I have reduced this to a very short, compileable example.
Test.h
#include <vector>
class Test{
public:
Test();
~Test();
protected:
std::vector<int> Ints;
};
And the main.cpp:
#include "Test.h"
int main(int argc, char **argv){
Test* t;
delete[] t;
return 0;
}
In the Implementation file is just empty constructor and destructors.
Something to note is, this only happens when the "Test" is a pointer, which would preferred to be avoided.
Will provide more information if needed. Thanks in advance.
You are deleting something that hasn't allocated a memory and that too in wrong way.
Allocate memory first
Test *t = new Test;
then,
delete t; // Note no []
Also, since C++11 is tagged, prefer using smart pointers, which do the memory management for you on its own
If t is a pointer then you need to give it something to point to first, as #P0W points out. But why not just declare t to be a local (stack) variable?
#include "Test.h"
int main(int argc, char **argv){
Test t;
return 0;
}
You are not creating object Test. You have created an pointer of type Test. For a pointer you need to use the keyword "new".
Test * t = new Test();

Eclipse Luna CDT: What is a header variant?

I am having difficulty getting the Eclipse Indexer (Codan) to recognize certain data declarations in header files. There is a new preference to Index all header variants, but little explanation as to what this means. Enabling the preference seems to fix the problem. But I still would like to know what the preference does exactly.
Let's say you have header a.h like this:
#pragma once
#ifndef SYMBOL
#define SYMBOL int
#endif
struct S
{
SYMBOL sym;
};
And now if you include your header like this:
struct UserSymbol
{
int i, j, k;
};
#define SYMBOL UserSymbol
#include "a.h"
S var;
int main()
{
var.sym.i = 123;
return 0;
}
then Eclipse CDT may not to recognize sym.i.
You may have more complex examples with deeper nested inclusions or so on.
EDIT:
But if you include the a.h to the "Index all variants of specific headers" list or check "Index all header variants" Eclipse will build several variants of the a.h indexes and will "know" that you have defined the your specific SYMBOL.

Why does Perl access to cross-platform packed structs not work with SWIG?

Working from:
Is ignoring __attribute__((packed)) always safe in SWIG interfaces?
Visual C++ equivalent of GCC's __attribute__ ((__packed__))
My .i does:
#define __attribute__(x)
then uses %include to include my cross-platform definition of PACK():
#if defined(SWIG)
#define PACK(...) VA_ARGS
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
Then I have code like:
PACK(
typedef struct {
uint8_t something;
uint32_t more;
} ) aName;
With earlier versions of the PACK() macro, I got syntax error from SWIG on the typedef line. Now I get past that but when compiling the SWIG-generated .c file, I have get and set functions that complain aName doesn't exist. The messages are like (edited):
libudr_perl_swig.c: In function '_wrap_aName_set':
libudr_perl_swig.c:2367:20: error: expected identifier or '(' before
'=' token libudr_perl_swig.c: In function '_wrap_aName_get':
libudr_perl_swig.c:2377:3: error: expected expression before 'aName'
SWIG sort of seems to know about my struct -- it creates access functions -- but the doesn't expose them enough that the access functions can find it.
Before I started to make this cross-platform -- when it was still Linux-only with __attribute__ ((packed)) -- it worked in SWIG. And it still works in Linux. So there appears to be something about SWIG's interpretation of PACK() that is flawed.
The old way generated a lot of per-field code like:
XS(_wrap_aName_something_set) {
{
aName *arg1 = (aName *) 0 ;
...
the new way generates a little per-struct code like:
SWIGCLASS_STATIC int _wrap_aName_set(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) {
MAGIC_PPERL
{
Why should my PACK() (which should be a no-op in SWIG) do that?
Googling "cpp standard variadic macros" leads to http://en.wikipedia.org/wiki/Variadic_macro which notes the expansion of ... is __VA_ARGS__, not VA_ARGS (as I had found somewhere). When I change my macro definition to be:
#if defined(SWIG)
#define PACK(...) __VA_ARGS__
#elif defined(_MSC_VER)
#define PACK(__Decl__) __pragma(pack(push, 1)) __Decl__ __pragma(pack(pop))
#else // GCC
#define PACK(__Decl__) __Decl__ __attribute__ ((packed))
#endif
it works.

Eclipse undefined reference

I'm using Eclipse and MinGW. I've got undefined reference to error to all that I write in h files, that I do include in cpp-file where main located. I create an empty project, and the same thing again (
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(){
Stack<int> stack(10);
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
stack.h
#ifndef STACK_H_
#define STACK_H_
template <class T>
class Stack{
private:
struct StackEl;
StackEl *top;
public:
Stack();
Stack(T el);
~Stack();
void Push(const T& el);
T Pop();
};
#endif /* STACK_H_ */
and stack.cpp inplements everything from stack.h
If I include not h-file, but cpp - all works. Help please!
I've got following errors
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:16: undefined reference to `Stack<int>::Stack(int)'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
D:/Workspacee/Stack2/Debug/../src/Stack2.cpp:18: undefined reference to `Stack<int>::~Stack()'
This is a linker error. I'm no Eclipse expert, but you have to tell it somehow to add Stack.o to the linking command.
If you include Stack.cpp instead of Stack.h, the implementations from the cpp-file get included into main.cpp by the preprocessor before compilation, so the linking stage has no unresolved references to outside functions.
My bad, that is becouse templates! When you use template, all code, including realization of functions, must be in header-file, or you have to write prototypes for every type you are going to use you template-functions with. I've forgot about that working with templates is not the same as with usual function :(