How can I initialize class variables in a header? - c++

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?

Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.

What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).

Related

How do I assign to a const variable using an out parameter in C++?

In a class header file Texture.h I declare a static const int.
static const int MAX_TEXTURE_SLOTS;
In Texture.cpp I define the variable as 0.
const int Texture::MAX_TEXTURE_SLOTS = 0;
Now in Window.cpp class's constructor I attempt to assign to the variable using an out parameter, however this obviously does not compile as &Texture::MAX_TEXTURE_SLOTS points to a const int* and not an int* .
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &Texture::MAX_TEXTURE_SLOTS);
I have tried using const_cast, but am greeted with a segmentation fault on runtime.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, const_cast<int*>(&Texture::MAX_TEXTURE_SLOTS));
I have also tried directly casting to an int * but once again, seg fault.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (int*)&Texture::MAX_TEXTURE_SLOTS);
Many thanks.
EDIT 2: So since you're trying to abstract OpenGL contexts, you'll have to let go of the "traditional" constructor/destructor idioms. And just for your information (unrelated to this question): OpenGL contexts are not tied to windows! As long as a set of windows and OpenGL contexts are compatible with each other, you may mix and match any way you like. But I digress.
The standard idiom to deal with a situation like yours is to use preinitializing factory functions. Like this:
class MyOpenGLContextWrapper {
public:
// Yes, shared_ptr; using a unique_ptr here for objects that are kind
// of a nexus for other things -- like an OpenGL context -- just creates
// a lot of pain and misery. Trust me, I know what I'm talkink about.
typedef std::shared_ptr<MyOpenGLContextWrapper> ptr;
struct constdata {
NativeGLContextType context;
// ...
GLint max_texture_image_units;
// ...
};
static ptr create();
protected:
MyOpenGLContextWrapper(constdata const &cdata) : c(cdata) {};
virtual ~MyOpenGLContextWrapper();
constdata const c;
}
MyOpenGLContextWrapper::ptr MyOpenGLContextWrapper::create()
{
struct object : public MyOpenGLContextWrapper {
object(MyOpenGLContextWrapper::constdata const &cdata) : MyOpenGLContextWrapper(cdata) {}
~object(){}
};
MyOpenGLContextWrapper::constdata cdata = {};
// of course this should all also do error checking and failure rollbacks
cdata.context = create_opengl_context();
bind_opengl_context(cdata.context);
// ...
glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, &cdata.max_texture_image_units);
return std::make_shared<object>(cdata);
}
EDIT: I just saw that you intend to use this to hold on to a OpenGL limit. In that case you can't do this on a global scope anyway, since those values depend on the OpenGL context in use. A process may have several OpenGL contexts, each with different limits.
On most computer systems you'll encounter these days, variables declared const in global scope will be placed in memory that has been marked as read only. You literally can't assign to such a variable.
The usual approach to implement global scope runtime constants is by means of query functions that will return from an internal or otherwise concealed or protected value. Like
// header.h
int runtime_constant();
#define RUNTIME_CONSTANT runtime_constant()
// implementation.c / .cpp
int runtime_constant_query(){
static int x = 0;
// NOTE: This is not thread safe!
if( !x ){ x = determine_value(); }
return x;
}
You can then fetch the value by calling that function.
Provided that glGetIntegerv doesn't depend on other gl* functions being called before, you may use an immediately-invoked lambda:
// Texture.cpp
const int Texture::MAX_TEXTURE_SLOTS = []
{
int maxTextureSlots{0}:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureSlots);
return maxTextureSlots;
}();
You don't.
You can't assign to a const outside of its definition. Also, using a const variable where the const has been const_casted away is UB. This also means you can't directly initialize a const variable with an output parameter. For trivial types, just output to another variable and make a const copy if you so wish.
If you were the author of the function you're calling, you would do well not to use out parameters, and then you could assign to const variables directly, perhaps using structured bindings if you want to name multiple of the outputs at a time. But here, you're not.

Reusing objects in functions defined in C++ header

I have a function library in a header file, which includes the following function:
// Get a normally distributed float value in the range [0,1].
inline float GetNormDistrFloat()
{
std::random_device _RandomDevice;
std::normal_distribution<float> _NormalDistr(0.5, 2.0);
float val = -1;
do { val = _NormalDistr(_RandomDevice); } while(val < 0.0f || val > 1.0f);
return val;
}
This works well, however, I don't want to create the std::random_device and std::normal_distribution objects every time I call this function GetNormDistrFloat().
What is the "best" (correct) way in C++ to deal with this? I tried to just move those two object definitions outside the function, but that led to linker errors. Do I have to create a .cpp file for this header and initialize the objects there?
You could mark them as static variables which makes them behave almost like globals but only accessible inside the function:
void bar() {
static Foo foo_instance;
// Foo gets initialized only once
}
The main difference is the initialization. Globals get initialized at startup and static variables at their first access.
You can also make them globals, just make sure you do not define them in a header file, instead declare them as external:
// Header file
extern Foo foo_instance;
// Cpp file
Foo foo_instance;
Initialization of local static objects is thread-safe, however everything else is not.
I'm am not a fan of other solutions mentioned here; such as using globals or static locals. For one, state in functions is not a good idea as it's implicit and not obvious when reading code. It also makes things more complicated if you want to use the function from multiple threads. And it also makes testing more complicated. Instead, the "correct" way to handle state is to do the boring thing and create a class:
class NormDistrFloatGenerator
{
public:
NormDistFloatGenerator(const std::random_device& device,
const std::normal_distribution<float>& normal)
: m_device(device)
, m_normal(normal)
{}
float get_float() { // use member variables with same logic as in question }
private:
std::random_device m_device;
std::normal_distribution<float> m_normal;
};
At least if you write this class, you can test it properly, or use it in multiple threads. You only have to initialize this class once, and then you can repeatedly generate floats. If you really want to have something convenient, you can then do:
NormDistFloatGenerator& void makeGlobalFloatGenerator() {
static NormDistFloatGenerator(std::random_device, std::normal_distribution<float>(0.5, 2.0);
}
// at namespace scope
auto& g_float_generator = makeGlobalFloatGenerator();
You can then use g_float_generator everywhere. I'd really encourage you to avoid this approach. And even more so avoid the shortcuts others are suggesting.

Char array initialisation in class

I am trying to unit test a C++ application that I am building and I'm having an issue initializing the array when used in a class. I've tried alot of different methods of loading this information, the only ones that work are inefficient / not suitable.
Here is the hex array that I have (randomised the parts)
0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10
And header file for my unit test:
class MessageParsingTest : public CPPUNIT_NS::TestFixture {
CPPUNIT_TEST_SUITE(MessageParsingTest);
CPPUNIT_TEST(testIdentifyFirstMessageType);
CPPUNIT_TEST_SUITE_END();
public:
MessageParsingTest();
virtual ~MessageParsingTest();
void setUp();
void tearDown();
private:
void testIdentifyFirstMessageType();
void testIdentifySecondMessageType();
// data members for the hex array
unsigned char firstMessage[1500];
};
Then in my test case setUp function;
void MessageParsingTest::setUp() {
firstMessage = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
}
That it my latest failed attempt, it says its not valid during compilcation, as I expected, but at this point I was trying anything.
I've also tried things like (all in setUp function)
firstMessage << "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
firstMessage[1500] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
and a few other crazy ways, Does anyone know the proper way to load this data? the only way I've had it working so far is with either no data member declaration and straight up defining it and initializing in one line (but then I cant access in the test cases) or doing it one by one like firstMessage[0] = 0x24; etc.
I understand that there will be a simple, proper way of doing this and considering what the application actually does, this part should be the easiest.
You have few options:
Initialize arrays in constructor MesssageParsingTest using syntax : firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10}
in initializer list.
Create static const array containing your message, and either copy it to member variable using memcpy, or use static member and get rid of firstMessage member variable.
Declare const static member in .h inside class definition:
static const unsigned char kFirstMessage[];
and define + initialize it in .ccp
const unsigned char MessageParsingTest::kFirstMessage[] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
I would prefer static const member if you do not intend to modify this array later, since it makes the intention cleaner.
Here is one way to do it.
void MessageParsingTest::setUp()
{
unsigned char x[] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
::memcpy(firstMessage, x, sizeof(x));
}
If you are using C++11, you can also initialize the firstMessage in the class member initialization list as
MessageParsingTest::MessageParsingTest() :
firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10},
...
You can use a temporary buffer and then copy into you member as this:
void MessageParsingTest::setUp() {
unsigned char tmp[1500] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
memcpy(firstMessage, tmp, 1500);
}

C++ Best practices for constants

I have a whole bunch of constants that I want access to in different parts of my code, but that I want to have easy access to as a whole:
static const bool doX = true;
static const bool doY = false;
static const int maxNumX = 5;
etc.
So I created a file called "constants.h" and stuck them all in there and #included it in any file that needs to know a constant.
Problem is, this is terrible for compile times, since every time I change a constant, all files that constants.h reference have to be rebuilt. (Also, as I understand it, since they're static, I'm generating a copy of doX/doY/maxNumX in code every time I include constants.h in a new .cpp, leading to kilobytes of wasted space in the compiled EXE -- is there any way to see this?).
So, I want a solution. One that isn't "declare constants only in the files that use them", if possible.
Any suggestions?
The only alternative is to make your constants extern and define them in another .cpp file, but you'll lose potential for optimization, because the compiler won't know what value they have when compiling each .cpp`.
By the way, don't worry about the size increase: for integral types your constants are likely to be inlined directly in the generated machine code.
Finally, that static is not necessary, since by default const global variables are static in C++.
You declare them as extern in the header and define them in an implementation file.
That way, when you want to change their value, you modify the implementation file and no full re-compilation is necessary.
The problem in your variant isn't compilation-related, but logic related. They will not be globals since each translation unit will have its own copy of the variable.
EDIT:
The C++-ish way of doing it would actually wrapping them in a class:
//constants.h
class Constants
{
public:
static const bool doX;
static const bool doY;
static const int maxNumX;
}
//constants.cpp
const bool Constants::doX = true;
const bool Constants::doY = false;
const int Constants::maxNumX = 5;
I think your base assumption is off.
Your other headers are usually organized by keeping together what works together. For example, a class and its related methods or two classes heavily interlinked.
Why group all constants in a single header ? It does not make sense. It's about as bad an idea as a "global.h" header to include every single dependency easily.
In general, the constants are used in a particular context. For example, an enum used as a flag for a particular function:
class File {
public:
enum class Mode {
Read,
Write,
Append
};
File(std::string const& filename, Mode mode);
// ...
};
In this case, it is only natural that those constants live in the same header that the class they are bound to (and even within the class).
The other category of constants are those that just permeate the whole application. For example:
enum class Direction {
Up,
Down,
Right,
Left,
Forward,
Backward
};
... in a game where you want to express objects' move regarding the direction they are facing.
In this case, creating one header file for this specific set of constants is fine.
And if you really are worried about grouping those files together:
constants/
Direction.hpp
Sandwich.hpp
State.hpp
And you will neatly sidestep the issue of recompiling the whole application when you add a constant... though if you need to, do it, you're paying the cost only once, better than a wrong-sided design you'll have to live off with for the rest of your work.
What is the problem with this usage?
Do not declare a static type in header file, It does not do what you think it does.
When you declare a static in header file a copy of that variable gets created in each Translation Unit(TU) where you include that header file, SO each TU sees a different variable, this is opposite to your expectation of having a global.
Suggested Solution:
You should declare them as extern in a header file and define them in exactly one cpp file while include the header with extern in every cpp file where you want to access them.
Good Read:
How should i use extern?
Another approach which is best for compile times (but has some minor run-time cost) is to make the constants accessible via static methods in a class.
//constants.h
class Constants
{
public:
static bool doX();
static bool doY();
static int maxNumX();
};
//constants.cpp
bool Constants::doX() { return true; }
bool Constants::doY() { return false; }
int Constants::maxNumX() { return 42; }
The advantage of this approach is that you only recompile everything if you add/remove/change the declaration of a method in the header, while changing the value returned by any method requires only compiling constants.cpp (and linking, of course).
As with most things, this may or may not be the best is your particular case, but it is another option to consider.
The straight forward way is, to create non const symbols:
const bool doX = true;
const bool doY = false;
const int maxNumX = 5;
These values will be replaced by the compiler with the given values. Thats the most efficient way. This also of course leads to recompilation as soon as you modify or add values. But in most cases this should not raise practical problems.
Of course there are different solutions:
Using static consts, (or static const class members) the values can be modified without recompilation of all refered files - but thereby the values are held in a const data segment that will be called during runtime rather than being resolved at compile tine. If runtime perfomance is no issue (as it is for 90% of most typical code) thats OK.
The straight C++ way is using class enums rather than global const identifiers (as noted my Mathieu). This is more typesafe and besides this it works much as const: The symbols will be resolved at compile time.

struct object declaration

hello every i have made a structure and i want to make 2 objects of it . i am using qtcreator.
i write
struct grapharray gao ; (grapharray is my structure)
every thig works well but when i write another object like
struct grapharray gao ;
struct grapharray gao1 ;
my program unexpectedly finishes can any one tell me why is it so and where should i declare the struct object
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
here is my structure;
and i have a function
struct grapharray graphplotdata(char * filename)
{ // computing some values and returning structure object
}
thanks
If I understand well the problem, I would say that you use far too much the "struct" keyword.
If you define your struct as
struct grapharray
{
int structcol;
double *structpayloadgraph;
double *structsessiongraph;
};
then you don't need to use the keyword "struct" when declaring the variables.
grapharray gao; // without struct keyword
grapharray gao1; // without struct keyword
and your function should be
grapharray graphplotdata(char * filename) // without struct once again.
{
// computing some values and returning structure object
}
structs does works almost the same way as classes; the main difference is that structs members and methods are "public" by default and classes members and methods are "private" by default.
Edit: Considering the comment of Dennis Zickefoose, this is not the good answer.