C++ error: fields must have a constant size - c++

can someone please give me a hint how to solve the following problem:
clang++-7 -pthread -std=c++17 -o main createLibrary/configuration.cpp createLibrary/growbox.cpp createLibrary/helper.cpp createLibrary/httprequests.cpp main.cpp
In file included from createLibrary/configuration.cpp:2:
In file included from createLibrary/configuration.h:1:
In file included from createLibrary/growbox.h:12:
createLibrary/httprequests.h:13:10: error: fields must have a constant size:
'variable length array in structure' extension will never be supported
char device[configuration::maxNameSize];
^
1 error generated.
I'm including the .h files in the order configuration.h, httprequests.h. I want all necessary config-parameters to be configured in the configuration.cpp file, but I got the displayed error. What am I doing wrong here?
configuration.h
extern int const maxNameSize;
configuration.cpp
int const configuration::maxNameSize = 30;
httprequests.h
char device[configuration::maxNameSize];
httprequests.cpp
char HTTPREQUESTS::device[configuration::maxNameSize];

An extern const int is not a constant expression.
a variable is usable in constant expressions at a point P if
the variable is
a constexpr variable, or
it is a constant-initialized variable
of reference type or
of const-qualified integral or enumeration type
and the definition of the variable is reachable from P
and
P is in the same translation unit as the definition of the variable
(emphasis added)
I want all necessary config-parameters to be configured in the
configuration.cpp file
You are out of luck. The value of maxNameSize must be visible to it's compile-time users.

Declare maxNameSize like this
// configuration.h
class configuration
{
public:
static const int maxNameSize = 30;
...
};
And no need to define it in configuration.cpp.
Your way doesn't make maxNamesize a compile time constant.
EDIT, I am assuming that configuration is a class. If it's a namespace then do the following instead
// configuration.h
namespace configuration
{
const int maxNamesize = 30;
...
}
Constants are an exception to the one definition rule, so it's OK to define them in a header file.

What am I doing wrong here?
You have defined an array variable with size that is not compile time constant.
Solution: You can either
Define the variable in the same translation unit where you use it as the size of an array so that it may be compile time constant. Given that the array is in a header, which presumably is included into multiple translation units, the size cannot be defined externally. It has to be either static or inline.
Or use a dynamic array instead. Simplest way to create dynamic array is to use std::vector.

Related

Class declaration in a header file and static variables

Noob question, but would like to understand the following:
Imagine I have a multifile project. I'm specifying a class in a header file to be shared among all the files in the project, and I write this : static int test = 0; and in the next line this: static const int MAX = 4;
The first one would be an error trying to compile because of the one definition rule. But the second one will compile without errors. Why?
From what I understand, both have the same properties: whole execution storage duration, class scope and no linkage.
Any help?
EDIT: testing an external constant declaration in a header: extern const int MAX = 4; to force external linkage produced the expected error. So I don't understand why with the variable it gives me the error and with the constant it doesn't.
Try
static const int test = 0;
I've sometimes noticed compiler errors with the immediate initialization of static const variables in the header file. You can always use the declaration in the header
class MyClass
{
// ...
static const int test;
// ...
}
and initialize it in the corresponding .cpp file
const int MyClass::test = 0;
This should work properly with any other types than int as well.
Integer constants in C++ don't actually occupy any space in the object and don't act like variables in general. Think about them more like numbers that are given names in this particular context.

Extern unnamed struct object definition

I got a global object of type "unnamed-struct" and i'm trying to define it. I don't want to pollute my global namespace with such useless type (it will be used only once).
Global.h
extern struct {
int x;
} A;
Is there any correct way to define such object?
I was trying this:
Global.cpp
struct {
int x;
} A = { 0 };
But VS2012 throws "error C2371: 'A' : redefinition; different basic types". Thanks.
One possible solution: create another file Global_A.cpp that does not include Global.h, and define A there. By the equivalent-definition rule this will be valid, as long as the anonymous struct definitions are equivalent.
This is still a bad idea, and most compilers will warn about it e.g. (gcc): warning: non-local variable `<anonymous struct> A' uses anonymous type.
There is no way to do just this simply because it would be error prone: some time in the future someone (probably even you) may want to modify this structure's definition and he might forget to do this in the header and source files accordingly. So you will have to invent a name for this structure and use its name the source file and leave its definition up to the header.
I don't know if this helps you, and this my first post... So take it easy.
I just ran into this issue and what I did was I added a function that manipulates the struct to the file that contained the anonymous struct. That way I can call that function from any file in my project, and it manipulates the values in the struct for me.
Here is an example:
header.c has this anonymous struct:
struct
{
char line1[80];
char line2[80];
char line3[80];
} header;
I want to manipulate those values in "interface.c" because I am making a command line interface in another file. My first instinct was to use an extern, but it seems like adding the following function to header.c is just as good or better (Some people discourage the use of externs when avoidable).
void changeHeaders(char *one, char *two, char *three);
void changeHeaders(char *one, char *two, char *three)
{
strcpy(header.line1, one);
printf("\nHeader 1: %s", header.line1);
strcpy(header.line2, two);
printf("\nHeader 2: %s", header.line2);
strcpy(header.line3, three);
printf("\nHeader 3: %s", header.line3);
}
Now as long as I include the prototype for that function I can manipulate those struct variables from any file by using that function. Hope that helps someone.

Why can I declare an array in a header file, but not a pointer?

I have a problem with my Consts.hpp file:
#pragma once
#include <stdafx.h>
namespace consts {
const GLchar* TEXTURE_DIR = "../../blabla/"; // doesn't work
const GLchar TEXTURE_DIR[14] = "../../blabla/"; // works
};
This file is added to the stdafx.h file. ColladaReader.cpp is the file where I access TEXTURE_DIR.
Why does the pointer not work in the namespace? When accessing the constant I get this error:
Error 5 error LNK2005: "char const * const consts::TEXTURE_DIR" (?TEXTURE_DIR#consts##3PBDB) already defined in ColladaReader.obj D:\Privat\code\openglearn\projects\ColladaReader\stdafx.obj
The issue here is that if you put this code in a header file, every .cpp file that includes it will think that it has the one unique copy of consts::TEXTURE_DIR. This will cause a linker error when you compile the code, because the linker will find multiple copies of this variable and will not know which one it should use.
The reason why the first version doesn't work while the second one does is subtle. In C++, any constant at file scope automatically has internal linkage and therefore sidesteps the above problem (since the linker treats each copy as separate). When you declared the array, your array itself is a constant:
const GLchar TEXTURE_DIR[14] = "../../blabla/";
However, the pointer you declared is not a constant:
const GLchar* TEXTURE_DIR = "../../blabla/";
The reason for this is that the pointer points at GLchars that are constant, but the pointer itself can be reassigned. For example, the line
consts::TEXTURE_DIR = "Now I'm different!"
will compile just fine.
To fix this, change the pointer declaration so that it is a constant pointer:
const GLchar* const TEXTURE_DIR = "../../blabla/";
Note the second const here, which means that the pointer cannot be reassigned. This should resolve the linker error.
Hope this helps!

Undefined reference C++

I have a file called Student.h which have the static integers in this way:
class Student
{
public:
static int _avrA,_avrB,_avrC,_avrD;
};
and I have university.h that inherits Student.h .
On the implementation of University.cpp , one of the functions returns:
return (_grade_average*(Student::_avrA/Student::_avrB))+7;
and the compiler writes:
undefined reference to Student::_avrA.
Do you know why it happens?
You have declared those variables, but you haven't defined them. So you've told the compiler "Somewhere I'm going to have a variable with this name, so when I use that name, don't wig out about undefined variables until you've looked everywhere for its definition."1
In a .cpp file, add the definitions:
int Student::_avrA; // _avrA is now 0*
int Student::_avrB = 1; // _avrB is now 1
int Student::_avrC = 0; // _avrC is now 0
int Student::_avrD = 2; // _avrD is now 2
Don't do this in a .h file because if you include it twice in two different .cpp files, you'll get multiple definition errors because the linker will see more than one file trying to create a variable named Student::_avrA, Student::_avbB, etc. and according to the One Definition to Rule Them All rule, that's illegal.
1 Much like a function prototype. In your code, it's as if you have a function prototype but no body.
* Because "Static integer members of classes are guaranteed to be initialised to zero in the absence of an explicit initialiser." (TonyK)
You have to define the static data members as well as declaring them. In your implementation Student.cpp, add the following definitions:
int Student::_avrA;
int Student::_avrB;
int Student::_avrC;
int Student::_avrD;

Beginner C++ - Trouble using global constants in a header file

Yet another Scrabble project question... This is a simple one.
It seems I am having trouble getting my global constants recognized:
My board.h:
http://pastebin.com/7a5Uyvb8
Errors returned:
1>C:\Users\Francisco\Documents\FEUP\1A2S\PROG\projecto3\projecto3\Board.h(34): error: variable "TOTAL_ROWS" is not a type name
1> vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1>
1>main.cpp
1>compilation aborted for .\Game.cpp (code 2)
1>Board.cpp
1>.\Board.h(34): error: variable "TOTAL_ROWS" is not a type name
1> vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1> ^
1>
Why does this happen? Why is the compiler expecting types?
Thanks for your time!
EDIT:
Disregard my previous edit...
This is my default constructor:
Board::Board()
{
_matrix(TOTAL_ROWS, vector(TOTAL_COLUMNS));
}
I get the following error.
1>.\Board.cpp(16): error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
1> _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS));
1> ^
Why does this happen?
I managed to solve all the problems with my file. I used
Board::Board() :
_matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS))
{}
instead. Thanks for all your help!
The way that is written, you are defining a function called _matrix that returns a vector. So TOTAL_ROWS is expected to be a type name, since it is being parsed as a paramter type. I assume what you are trying to do is define a variable called _matrix that is a vector.
What you want to do is leave off the constructor, and initialize the variable inside your constructor. Only constant integral values can be initialized in the body of the class, at least in the current version of the standard.
Leaving off the unimportant parts:
Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) { }
private:
vector< vector<Cell> > _matrix;
Note that this is just an example. Presumably you have an implementation file with an actual body for Board(), and you should put the initialization there rather than directly in the header or you'll get errors. The important thing is that you should not do it when you declare _matrix initially.
For your new question, extern const unsigned int TOTAL_COLUMNS = 15; defines TOTAL_COLUMNS every time Board.h is included by a file. Constant variables at namespace scope have internal linkage by default, so if you leave off the extern you will be okay.
In general, if the variable isn't constant, you take an approach similar to the one for _matrix. You leave off the initialization in the header, and then inside an implemenation file put it back on:
board.h:
extern const int TOTAL_COLUMNS;
board.cpp:
extern const int TOTAL_COLUMNS = 15;
You try to initialize the vector on it's definition, which is not the correct way to do this for object variables, the correct way is this:
extern const unsigned int TOTAL_ROWS = 15;
extern const unsigned int TOTAL_COLUMNS = 15;
class Board
{
public:
Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) {}
private:
vector< vector<Cell> > _matrix;
};
In your header file, I see:
private:
vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
This seems to be declaring a private member variable, _matrix, and is apparently an effort to call the constructor for _matrix at the same time. You cannot call the constructor in this way.
Remember that your header file may be included in MANY program files.
As a result, headers should not contain execution instructions (certain exceptions exist, such as inline methods and templates). You never know where the header will be included, so you never know where the code in a headerfile will appear.
It is good advice to write your header files so that they are safe to be included anywhere.
If you want to continue this code, I suggest:
The constructor of Board() should construct the member variable explicitly:
Board::Board() :
_matrix(TOTAL_ROWS, .....);
// This will call the matrix constructor ONLY when the Board constructor is called.
{
}
Then the Board constructor should be called, but ONLY in a .cpp file, not in a .h file.
This is my default constructor:
Board::Board() { _matrix(TOTAL_ROWS,
vector(TOTAL_COLUMNS)); }
I get the following error. [ .... ]
You did not follow the examples and syntax provided by #Dennis Zickefoose, #KillianDS, and myself.
Please re-read our answers and study our code.
You can't call a constructor in the header file (or any code for that matter).