How do I set constant configuration parameters at run-time - c++

I am trying to achieve the following. I want to store some of the system information in a set of variables.
Say the variables are:
std::string GPU;
std::string CPU;
std::string OS;
I want these variables to have global scope, but only for reading (they should not be modified). Normally for this one would simply append const to the declaration. However for some of these variables I need to find the information at runtime after main has executed.
The issues is thus that I cannot simply initialize them statically as one normally would, I need to wait until some processing has been made to set them.
Overall I need the variables to be initialized once and exactly once by a function and then just be readable.
Is this achievable at all?

Why not hide required constants behind private static scope of a struct? In multithreaded environment you may even add a conditional variable and wait for initialization.
struct globals {
static const std::string& GPU() {assert(is_inited_); return gpu_;}
static init(std::string GPU, ...) {gpu_ = std::move(GPU); ...; is_inited_ = true;}
private:
std::string gpu_;
std::string cpu_;
std::string os_;
book is_inited_;
};
int main() {
...
// initialize consts at some point
globals::init();
...
// access consts
globals::GPU();
}
// initial values
std::string globals::gpu_;
...
bool globals::is_inited_ = false;

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.

C++ global extern constant defined at runtime available across multiple source files

I have an integer constant that is to be defined at runtime. This constant needs to be available globally and across multiple source files. I currently have the following simplified situation:
ClassA.h declares extern const int someConstant;
ClassA.cpp uses someConstant at some point.
Constants.h declares extern const int someConstant;
main.cpp includes ClassA.h and Constants.h, declares const int someConstant, and at some point during main() tries to initialize someConstant to the real value during runtime.
This works flawlessly with a char * constant that I use to have the name of the program globally available across all files, and it's declared and defined exactly like the one I'm trying to declare and define here but I can't get it to work with an int.
I get first an error: uninitialized const ‘someConstant’ [-fpermissive] at the line I'm declaring it in main.cpp, and later on I get an error: assignment of read-only variable ‘someConstant’ which I presume is because someConstant is getting default initialized to begin with.
Is there a way to do what I'm trying to achieve here? Thanks in advance!
EDIT (per request from #WhozCraig): Believe me: it is constant. The reason I'm not posting MCVE is because of three reasons: this is an assignment, the source is in Spanish, and because I really wanted to keep the question as general (and reusable) as possible. I started out writing the example and midway it striked me as not the clearest question. I'll try to explain again.
I'm asked to build a program that creates a process that in turn spawns two children (those in turn will spawn two more each, and so on). The program takes as single argument the number of generations it will have to spawn. Essentially creating sort of a binary tree of processes. Each process has to provide information about himself, his parent, the relationship with the original process, and his children (if any).
So, in the example above, ClassA is really a class containing information about the process (PID, PPID, children's PIDs, degree of relation with the original process, etc). For each fork I create a new instance of this class, so I can "save" this information and print it on screen.
When I'm defining the relationship with the original process, there's a single point in which I need to know the argument used when calling the program to check if this process has no children (to change the output of that particular process). That's the constant I need from main: the number of generations to be spawned, the "deepness" of the tree.
EDIT 2: I'll have to apologize, it's been a long day and I wasn't thinking straight. I switched the sources from C to C++ just to use some OO features and completely forgot to think inside of the OO paradigm. I just realized while I was explaining this that I might solve this with a static/class variable inside my class (initialized with the original process), it might not be constant (although semantically it is) but it should work, right? Moreover I also realized I could just initialize the children of the last generation with some impossible PID value and use that to check if it is the last generation.
Sorry guys and thank you for your help: it seems the question was valid but it was the wrong question to ask all along. New mantra: walk off the computer and relax.
But just to recap and to stay on point, it is absolutely impossible to create a global constant that would be defined at runtime in C++, like #Jerry101 says?
In C/C++, a const is defined at compile time. It cannot be set at runtime.
The reason you can set a const char *xyz; at runtime is this declares a non-const pointer to a const char. Tricky language.
So if you want an int that can be determined in main() and not changed afterwards, you can write a getter int xyz() that returns a static value that gets initialized in main() or in the getter.
(BTW, it's not a good idea to declare the same extern variable in more than one header file.)
As others have mentioned, your variable is far from being constant if you set it only at run-time. You cannot "travel back in time" and include a value gained during the program's execution into the program itself before it is being built.
What you can still do, of course, is to define which components of your program have which kind of access (read or write) to your variable.
If I were you, I would turn the global variable into a static member variable of a class with a public getter function and private setter function. Declare the code which needs to set the value as a friend.
class SomeConstant
{
public:
static int get()
{
return someConstant;
}
private:
friend int main(); // this should probably not be `main` in real code
static void set(int value)
{
someConstant = value;
}
static int someConstant = 0;
};
In main:
int main()
{
SomeConstant::set(123);
}
Anywhere else:
void f()
{
int i = SomeConstant::get();
}
You can further hide the class with some syntactic sugar:
int someConstant()
{
return SomeConstant::get();
}
// ...
void f()
{
int i = someConstant();
}
Finally, add some error checking to make sure you notice if you try to access the value before it is set:
class SomeConstant
{
public:
static int get()
{
assert(valueSet);
return someConstant;
}
private:
friend int main(); // this should probably not be `main` in real code
static void set(int value)
{
someConstant = value;
valueSet = true;
}
static bool valueSet = false;
static int someConstant = 0;
};
As far as your edit is concerned:
Nothing of this has anything to do with "OO". Object-oriented programming is about virtual functions, and I don't see how your problem is related to virtual functions.
char * - means ur creating a pointer to char datatype.
int - on other hand creates a variable. u cant declare a const variable without value so i suggest u create a int * and use it in place of int. and if u are passing it into functions make it as const
eg: int *myconstant=&xyz;
....
my_function(myconstant);
}
//function decleration
void my_function(const int* myconst)
{
....
}
const qualifier means variable must initialized in declaration point. If you are trying to change her value at runtime, you get UB.
Well, the use of const in C++ is for the compiler to know the value of a variable at compile time, so that it can perform value substitution(much like #define but much more better) whenever it encounters the variable. So you must always assign a value to a const when u define it, except when you are making an explicit declaration using extern. You can use a local int to receive the real value at run time and then you can define and initialize a const int with that local int value.
int l_int;
cout<<"Enter an int";
cin>>l_int;
const int constNum = l_int;

Hiding queryable program state without using a class?

Consider a library exporting a distinct interface for initialization, which has to be called by the user before using anything else the library provides. In this step, certain system state is queried and stored in corresponding variables. This cannot be mapped to constants, but should also not be prone to changes due to writes from external sources, i.e. the system state should be queryable in different translation units but not writable.
One obvious example is a timestamp marking the system startup. This cannot be a compile-time constant, but should also never be writable.
This could be realized with a class implementing only static functions and using private, static members:
// system.h
#include <chrono>
using sys_time_point = std::chrono::system_clock::time_point;
class System
{
public:
System () = delete;
// possibly other deleted functions
static bool init () noexcept;
static bool ready () noexcept;
static const sys_time_point& initTime() noexcept;
private:
static bool initState_;
static sys_time_point initTime_;
};
// system.cpp
bool System::initState_ = false;
sys_time_point System::initTime_ = std::chrono::system_clock::now();
The thing is, I consider the latter approach an inadequate design choice because the functions, although possibly dependent on each other, define more or less miscellaneous functionality for querying system state, not modifying or accessing private state of user-defined type.
I'd much rather go for the second approach. Suppose a namespace System which groups the same functionality as the prior class did
// System.h
#include <chrono>
namespace System
{
using sys_time_point = std::chrono::system_clock::time_point;
bool init () noexcept; // needs to be called
bool ready () noexcept; // can be used by other lib components and lib clients
const sys_time_point& initTime() noexcept; // returns system startup time point
// other stuff here ...
}
// System.cpp
namespace System
{
namespace
{
bool sysInitState = false;
sys_time_point sysInitTime = std::chrono::system_clock::now();
}
bool init() noexcept
{
// init code here ... set and return sysInitState accordingly
}
bool ready() noexcept
{
return sysInitState;
}
const sys_time_point& initTime() noexcept
{
return sysInitTime;
}
}
Using the unnamed namespace, I suppress linking to the variables externally in other translation units. AFAIK, there is no way to access them in other translation units except using the functions in namespace System. Writing is also not possible due to const refs or returns by value - except for the scenario where an evil programmer might const_cast<> the const refs to non-const refs.
My questions would now be:
is the above, second solution correct at all?
is the above, second solution viable?
are there other solutions which might be more safe or easier to implement?
Thanks everyone!
Obscuring the private information in a namespace works, but I recommend putting them in a struct and storing one copy of that struct in a local variable.
// System.cpp
namespace {
struct SysInit
{
bool state;
sys_time_point time;
SysInit()
: state(false)
, time (std::chrono::system_clock::now())
{ }
static SysInit& instance()
{
static SysInit rval;
return rval;
}
};
}
void init() noexcept
{
SysInit::instance().state = true;
}
bool ready() noexcept
{
return SysInit::instance().state;
}
const sys_time_point& initTime() noexcept
{
return SysInit::instance().time;
}
The reason for this peculiar trick is there is no order of initialization for globals in different .cpp files. If one of your user's .cpp files calls init() in your example before sysInitTime gets initialized, init may use bad values, or worse, the sysInitTime initializer might change its value, which your library doesn't want.
Static local variables are guaranteed to be initialized once, the first time a function gets called. By storing the data in a static local variable rather than a global, we ensure you have constructed values ready to work with. By putting them in a struct together with one function that returns the whole group, we make it easier on the developer to prove that they are all indeed constructed and up to date (not essential for the algorithm, but it makes it much easier to make sense of the code).
A similar pattern is used by boost, but instead of putting them in an anonymous namespace in a .cpp, they put the variables inside a namespace boost::detail. Boost openly states that if you start mucking around inside boost::detail undefined behavior can occur. They do this because many of their libraries are header only, and don't have a .cpp file to work with. I bring it up because having a detail namespace has become an accepted way of saying "no-touch" to implementation details.

const correctness for configuration structures

I have a configuration file which gets read in, parsed and put into structures at the beginning of my programs run time.
The problem I am having is that I want these structures to be constant since the values in them should not change during the programs lifespan.
Currently I am doing the following:
config.h
#pragma warning(push)
#pragma warning(disable: 4510) /*-- we don't want a default constructor --*/
#pragma warning(disable: 4610) /*-- we don't want this to ever be user instantiated --*/
typedef struct SerialNode {
private:
void operator=(SerialNode&);
public:
const char* const port;
const char* const format;
} SerialNode;
#pragma warning(pop)
typedef std::map<const char*, const SerialNode*, MapStrComp> SerialMap;
SerialMap SerialConfig;
config.cpp
/*-- so we don't fall out of scope --*/
SerialNode* global_sn;
SerialNode local_sn = {port, format};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
This works fine. However my problem is that now I am dealing with more complicated configuration data which requires me to pull a structure back out of the list, modify it and then put it back.
Obviously I can't modify it, so the solution would be something like:
SerialNode* global_sn;
SerialNode* old_sn = SerialConfig[key_store];
SerialNode local_sn = {port, format, old_sn->old_data, old_sn->more_old_data};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
delete old_sn;
But this strikes me as bad programming practice. Is there is a better way to achieve what I'm going for which doesn't require such a hacked looking solution?
For reference, I'm using Visual Studio 2010
As always, the best thing you can do is not re-implement something that has already been written. There are a large number of libraries and frameworks that will help with serialization for c++:
Boost Serialization
Qt
Protocol Buffers
msgpack
Capn' Proto
Ideally the serialization framework you choose will exactly recreate the data graph that you are trying to store. Regardless of whether you have done any fixup, your goal will likely be to only provide const access to the global configuration data. Just make sure that mutators (including non const pointers) are not exposed via a header file.
The simple answer is what Thomas suggest, but correctly done (that is, not causing undefined behavior):
Create a mutable configuration object but pass it to the rest of the components by constant reference. When you create (and where you maintain) the real object you can change it, but the rest of the application won't be able to modify the config. A common pattern I have used in the past was:
class SomeObject {
Configuration const & config;
public:
SomeObject(Configuration const & config) : config(config) {}
void f() {
if (config.someParam()) { ...
// ...
void loadConfiguration(Config & config) { ... }
int main() {
Configuration config;
loadConfiguration(config); // config is a non-const &, can modify
SomeObject object(config); // object holds a const&, can only read
object.f();
// ...
This is not an answer to your question, just some observations to your code.
You don't need the typedef struct SerialNode { ... } SerialNode;, this is a c idiom. In c++, you just write struct SerialNode { ... }; and use SerialNode as a type name.
If you want to prevent a default constructor, make it private as you already do with the assignment operator
class SerialNode {
private:
SerialNode();
SerialNode &operator=(SerialNode&);
...
};
Don't use char* members, use std::string instead. C++ strings are much easier and safer to use than plain char pointers and the associated heap allocation.
Same goes for the map key; if you use std::string as a key, you don't need MapStrComp anymore, because std::string already provides an appropriate comparison.
Probably nicer is to wrap the whole thing in a singleton class:
class Config {
public:
static Config const& get() { return *config; }
static void load();
SerialNode const* operator[](const char*);
private:
static Config* config;
SerialMap map;
};
void Config::load() {
config = new Config();
// put things into it
}
Disclaimer: not tested, and haven't used C++ in a while, so there might be some syntax errors :)

Static variable definition order in c++

Hi i have a class tools which has static variable std::vector m_tools.
Can i insert the values into the static variable from Global scope of other classes defined in other files.
Example:
tools.h File
class Tools
{
public:
static std::vector<std::vector> m_tools;
void print()
{
for(int i=0 i< m_tools.size() ; i++)
std::cout<<"Tools initialized :"<< m_tools[i];
}
}
tools.cpp File
std::vector<std::vector> Tools::m_tools; //Definition
Using register class constructor for inserting the new string into static variable.
class Register
{
public:
Register(std::string str)
{
Tools::m_tools.pushback(str);
}
};
Different class which inserts the string to static variable in static variable
first_tool.cpp
//Global scope declare global register variable
Register a("first_tool");
////////
second_tool.cpp
//Global scope declare global register variable
Register a("second_tool");
Main.cpp
void main()
{
Tools abc;
abc.print();
}
Will this work?
In the above example on only one string is getting inserted in to the static list. Problem look like "in Global scope it tries to insert the element before the definition is done"
Please let me know is there any way to set the static definiton priority? Or is there any alternative way of doing the same.
You are likely, here, to encounter the issue referred to as Initialization Order Fiasco.
The problem is that the initialization order of globals (and static class variables are globals) is well-defined within a same translation unit (roughly, think .cpp) but is completely undefined across translation units. Therefore, there is no guarantee that the vector be initialized when you try to push items in there.
Your solution here ? Use local static variables:
class Tools
{
public:
static std::vector<std::string>& AccessTools()
{
static std::vector<std::string> Tools; // local static
return Tools;
}
private:
};
class Register
{
public:
Register(std::string str)
{
Tools::AccessTools().push_back(str);
}
};
It is guaranteed to be initialized upon first access... though it's not (and cannot be) thread safe; if you are in a multithreading situation, you need to call Tools::AccessTools in main before launching the other threads to guarantee the initialization.
The initialization order of static global variables in different compilation units is not defined in C++ - this is why you have a problem.
A workaround may be to call a static function which contains the first static variable as local. This way you can force it to be initialized before it is used:
// tools.h
class Tools
{
public:
static std::vector<std::vector>& getTools();
...
};
// tools.cpp
std::vector<std::vector>& Tools::getTools() {
static std::vector<std::vector> tools;
return tools;
}
...
class Register
{
public:
Register(std::string str)
{
Tools::getTools().pushback(str);
}
};
The initialization of statics is not specified by C++. C++ FAQ Lite call it the "static initialization order fiasco"
my2c