Proper implementation of global configuration - c++

My goal is to have global constants in a C++ game I'm working on (to represent some graphics info and the like). My current implementation is to toss them all in a .h and include them everywhere. This works, except that every time I change a setting, the entire code base must be recompiled.
So, my next idea was to toss them in some configuration txt file and parse them in, that way no code is actually changed when settings change. The parser was simple enough, and I could put the values into the constants, but because the parser was a code block, the constants were no longer global.
Is there a good way to solve this? Perhaps some way to make them global despite being in a block or some way to avoid recompiling everything when changing settings?

The way I used solve this is to put the variables in a separate global namespace, which is in a header file named something like config.h, then include that file everywhere.
// In config.h
#ifndef CONFIG_H
#define CONFIG_H
namespace config
{
extern int some_config_int;
extern std::string some_config_string;
bool load_config_file();
}
#endif
Then in a source file, you define the variable and also set them to a default value. This source file also have the code to load the variables from your configuration file.
// In config.cpp
namespace config
{
int some_config_int = 123;
std::string some_config_string = "foo";
}
bool config::load_config_file()
{
// Code to load and set the configuration variables
}
Now in every source file you need the configuration variables, include config.h and access them like config::some_config_int.
However, there is no "proper" way of solving this, all ways that work are proper in my eyes.

Another way to do this would be to create a singleton class.
#include <fstream>
#include <map>
#include <string>
class ConfigStore
{
public:
static ConfigStore& get()
{
static ConfigStore instance;
return instance;
}
void parseFile(std::ifstream& inStream);
template<typename _T>
_T getValue(std::string key);
private:
ConfigStore(){};
ConfigStore(const ConfigStore&);
ConfigStore& operator=(const ConfigStore&);
std::map<std::string,std::string> storedConfig;
};
Here the configuration is saved in a map, meaning as long as parseFile can read the file and getValue can parse the type there is no need to recompile the config class if you add new keys.
Usage:
std::ifstream input("somefile.txt");
ConfigStore::get().parseFile(input);
std::cout<<ConfigStore::get().getValue<std::string>(std::string("thing"))<<std::endl;

What about creating functions that return your constants that you can specify in a .cxx file? For example:
// foo.h
const int BAR();
// foo.cxx
const int BAR() {
return 10;
};

put only the declarations in head file and put the definitions in a cpp file. then you change the definitions in cpp file will not cause all code recompiled

Related

Use one globe variable in all cpp files.If one class of the cpp file changed the value,I want to access it from another class cpp file

I want to Use one globe variable in all cpp files.If one class of the cpp file changed the value,I want to access it from another class cpp file,which is the value that least modified by any other cpp class file.
str.h - global variable file
#ifndef MY_PROG
#define MY_PROG
extern char * myname;
#endif
class1.cpp
#include "str.h"
char * myname;
class class1
{
class1(){}
~class1(){}
void Setname1(char *name) { myname = name }
};
class2.cpp
#include "str.h"
char * myname;
class class2
{
class2(){}
~class2(){}
void setName(char *name) { myname = name }
};
class3.cpp
#include "str.h"
class class3
{
class3(){}
~class3(){}
char *GetData()
{
return myname;
}
};
main.cpp
#include "str.h"
int main()
{
class1 c1;
class2 c2;
c1.Setname1("XXXX");
c2.setname("YYYY");
class3 c3;
cout << c3.GetData;
}
when I execute the program, I need to get Last modified value that is "YYYY" .I am new to cpp, And also please tell me whether I used the extern keyword correctly.If not , please provide me the right procedure.
The essential in your problem is understanding the difference between declarations and definitions of variables (and types, functions etc. objects in C/C++)
extern char * myname; is a declaration. It makes myname visible to other pieces of code in the same file so that they can reference it.
char * myname; is a definition. Not only it makes myname visible, it also instructs the compiler to allocate space for it and to make its address known.
You can have as many declarations of the same variable in your code as you want, as long as they do not contradict each other. No so with definitions. If you define a thing two times, it would need to be assigned two addresses, and then how can other object files "understand" which address to use when referencing it? The same goes with the space allocated — what to do with the extra piece of it allocated? This is the error that you see.
To make the code work, have only one and exactly one definition of myname in exactly one file. It must not be a header file because it gets copied into multiple source files thus creating multiple definitions. It can be any other C++ file though.
In the rest of the files (or in a single header included in all of them) have multiple declarations of myname if it is referenced in a particular file. If not, you can omit it for a particular unit.
All this being said, it is considered to be a VERY BAD PRACTICE to communicate data between compilation units through global mutable shared variables. They make code a nightmare to debug and understand and impossible to parallelize. Nobody ever thinking getting money for the code they write should use them. Instead, the best approach would be to pass a mutable object as one of methods/functions argument. Details actually depend on the rest of your application.

How to manage file unique IDs in c++

c++ (not c++11)
Say i have 100 .cpp files in my project, which currently do some work.
All of those files currently include some globals.h file which i can edit easily.
I want each of those files to have its own instance of some object, and I also want that instance to have some unique ID of the file in which it is instantiated.
In addition, I want those objects to be created by a factory method, and I need the instances to have some way for a user to handle them - meaning they can't be anonymous.
In short - I need a way to generate unique IDs for all of the files in my project, i need the file to be able to access its own ID using the same name in all files, but also to be able to access the ID of a file externally in another "manager" file.
Here are options that don't work:
1.
Enum:
If I use an enum and give every file an enum ID, now I can't do this in globals.h:
static thePrivateInstanceInThisFile = theFactory.makeInstance(fileID);
because I need a different fileID in every file, and that was defined statically, and uniquely named using my enum.
2.
Class that counts its own instances
Define in globals.h:
class FileIDGiver{
private:
static int currentID;//initialize to 0 in cpp
int myID;
public:
FileIDGiver(){
myID = currentID++;
}
int getFileID(){
return myID;
}
}
static FileIDGiver theFileId;
static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());
This will give an ID to each static file instace which is unique to the file, but now it is not manageable externally to the file.
I thought about doing something like
globals.cpp
int file1ID;
int file2ID;
...
globals.h
extern file1ID;
extern file2ID;
...
file1.cpp
file1ID = theFileId.getFileID();
file2.cpp
file2ID = theFileId.getFileID();
...
and whenever a user needs to manage a file he would either use the file's ID variable, or create a new one in the above manner.
This would allow me to access each uniquely and automatically file ID externally.
The only problem I have with this is the line file1ID = theFileId.getFileID(); only executes in runtime, AFTER the line static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());.
which executes at compile time.
I can't figure out a good way to reverse this order, or maybe do a whole other mechanic.
Again - I need:
Automatically created file IDs
Unique file IDs (which are very very preferably numbers)
Usage of those IDs by the same variable name in all files (automatically, using a static variable definition in the globals.h file)
Ability to access a specific file ID manually by using another manually defined variable.
Please advise some good way to accomplish this
Thanks.
This sounds like a bad case of the static initialization order fiasco.
Here is a solution which uniquely assigns integer ids to each file, then generates a unique Instance by calling a factory function with the file's id, while ensuring that the Instance factory is initialized before its first use:
idgiver.h:
class IdGiver
{
int id;
public:
IdGiver() : id(0) {}
int getId() {return id++;}
};
IdGiver &getTheIdGiver();
idgiver.cpp:
#include "idgiver.h"
IdGiver &getTheIdGiver()
{
static IdGiver theIdGiver;
return theIdGiver;
}
factory.h:
class Instance
{
// ...
};
class Factory
{
// ...
public:
Factory() : {/*...*/}
Instance getInstance(int id) {/*...*/}
};
Factory &getTheFactory();
factory.cpp:
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
globals.h:
#include "idgiver.h"
#include "factory.h"
static int thisFileId = getTheIdGiver().getId();
static Instance thisFileInstance = getTheFactory().getInstance(thisFileId);
If you want to be able to access the static Instances of other files, then this cannot be done via an automatically generated id because the id generated for a file could change each time a new file is added, or every time it is compiled, or even on each execution. Therefore in this solution, each file manually defines its own persistent id similarly to example 1 in the question.
ids.h
enum FileId
{
File1, File2, File3
};
factory.h
#include "ids.h"
#include "instance.h"
class Factory
{
// ...
public:
Factory() {/*...*/}
Instance createInstance(FileId fileid) {/*...*/}
};
Factory &getTheFactory();
factory.cpp
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
idmanager.h
#include "ids.h"
#include "instance.h"
template<FileId id>
struct Manager
{
static Instance &getInstance(); // not defined
};
global.h
#include "idmanager.h"
#include "factory.h"
template <>
Instance &Manager<FILEID>::getInstance()
{
static Instance theInstance = getTheFactory().getInstance(FILEID);
return theInstance;
};
static Instance &getThisFileInstance()
{
return Manager<FILEID>::getInstance();
}
Usage is as follows: for each file requiring a static Instance object, place at the start
#define FILEID File1 // The FileId corresponding to this file
#include "global.h"
Then in any file,
The unique id is given by FILEID. (sorry it's a macro)
The static Instance of this file is obtained by getThisFileInstance().
The static Instance of any file is obtained by Manager<any_file_id>::getInstance().
This works by placing the implementation for an instantiation of the template Manager<FileId> in each file, each of which creates and returns that file's static Instance.
Advantages are persistence of ids, and zero run-time overhead: no need to dynamically assign ids, and the calls to Manager<file_id>::getInstance() are resolved at compile-time.
Also, the ids.h header can easily be generated by a script which scans the first line of each file for #define FILEID fileid, so the only maintenance left is remembering to write #define FILEID fileid.
You might modify your building procedure (e.g. your Makefile) to define some unique thing. E.g. you could compile your foo23.cpp file with something like (assuming GCC on some Linux system; adapt this to your compiler and OS and builder)
g++ -Wall -c -DBASENAME="$(basename foo23.cpp)" -DUNIQUEID=23
You could get the 23 for UNIQUEID using some shell script or whatever, e.g. an ad-hoc rule in your Makefile. Details depend upon your file naming conventions.
then use appropriately BASENAME and UNIQUEID in your C or C++ code (perhaps with dirty #if UNIQUEID==23 preprocessor tricks...).
So the idea is to generate the UNIQUEID in your build system and to pass it thru some preprocessor symbols. Details are OS, compiler, build-system specific.
You might also do some crude meta-programming by generating some C or C++ source or header file (perhaps using some awk script or some GPP or m4 preprocessing) in your building procedure.

Using a static variable of a shared library in more than one functions of a same exe, but different object file

(i have edited my original question to make it more understandable)
here is the prototype for the problem ....
//Txn.h ---this has a static variable, usable by the pgms including it.
class Txn
{
public:
static int i;
static void incr_int();
};
Txn::i=0;
//Txn.cpp
void Txn::incr_int() {i++;}
->produce LibTxn.so
//class1.cpp -> one of the pgm using the static var from Txn.h
#include Txn.h
Txn::incr_int()
-> produce class1.o, with LibTxn.so.
// class2.cpp ->another pgm using the static var from Txn.h
#include Txn.h
cout<<"Txn::i;
-> produce class2.o, by including LibTxn.so
-> .produce class3 (an exe) by using class1.o,class2.o. Since, both class1 and 2 has the statement "Txn::i=0" from "Txn.h", multiple declaration issue happens.
-> .If I remove the statement "Txn::i=0" from Txn.h, then "undefined reference" error appears.
-> .At high lvl, this problem is a kind of having a session variable, which should be assessible from any func in a exe. Those func can be in any obj files used to form the exe. I am fine for any sol, even without static. But I can't change the creation of different .o files (which are using this session var) and combining the .o to produce the exe.
It is hard to figure out exactly what the problem is if you cannot provide the real code, or at least an example which has the same problem as the real code.
However, most likely the root cause of the problem is that you are not only declaring, but also defining your class's static variable in the header file that contains the class definition.
This means that all the translation units (i.e. .cpp files) which include that header will contain a definition for the static variable, and when merging all the corresponding object files, the linker will eventually complain about that symbol being defined multiple times.
If this is the case, what you should do is to take the initialization of the static variable out of the header file which contains your class's definition and put it in one (and only one) .cpp file.
I tried to recreate the problem as you described, but it compiled just fine on my computer, and it is difficult to go further without seeing your code.
In the code below, the header tells (declares) every .cpp file that includes it about Foo::x, but Foo::x lives in (is defined in) Foo.cpp (and Foo.o)
foo.h:
class Foo {
public:
static int x;
};
Foo.cpp:
#include "foo.h"
int Foo::x;
main.cpp:
#include <iostream>
#include "foo.h"
int main(int argc, char *argv[]) {
Foo::x = 42;
std::cout << "Foo::x is " << Foo::x;
}
Yes. it worked by defining the static variable in .cpp.
Special thanks to Andy Prowl and iWerner.

List Variable in Library Causes run time error, why?

OK folks. I have fixed the error by moving the variable definition, but I do not understand why there is a problem.
Simplified Background: I have an object and I want to track all instances of that object in a list, so I simply created a List<> static member of the class. Below was a simple representation that allowed me to play with it. If I have the line marked as "this line" in the static library. I get a run time error. The object is defined in a header file and is the same header file in both places. If I move "this line" to the code in my final application and it works.... Why? I just don't understand why it is different.
#include "stdafx.h"
#include <list>
using namespace std;
class someobject
{
public:
someobject()
{
// do some stuff.
theStaticList.push_back(this);
}
void func()
{
printf("Made it!!\n");
}
static list<someobject*> theStaticList;
};
list<someobject*> someobject::theStaticList; //*** This line
someobject global;
int main()
{
someobject initial;
initial.func();
global.func();
list<someobject*>::iterator iter;
printf("\n\nLoop the Static List\n");
for (iter = someobject::theStaticList.begin(); iter != someobject::theStaticList.end (); iter++)
(*iter)->func();
return 0;
}
If you put that line in a header file, then include the header into two or more source files, you're defining the list object in each source file where the header gets included.
This violates the one definition rule, so the linker will quite rightly give you an error when you do it.
You want to define the object in one (and only one) source file. For a library, that should be some object file in the library, not the user's source file though (at least as a general rule).

how to use not yet defined datatypes in a header?

I am programming on linux using g++ and I often encounter the problem that I need to use a class or data type in a header file which I define later, either at a later point in the header or in another header file.
For instance look at this header file:
class example
{
mydatatype blabla;
};
struct mydatatype
{
int blablainteger;
char blablachar;
};
This will give error because mydatatype is used before its defined
so usually I change it like this:
struct mydatatype; // <-- class prototype
class example
{
mydatatype *blabla; // <-- now a pointer to the data type
// I will allocate the data during runtime with the new operator
};
struct mydatatype
{
int blablainteger;
char blablachar;
};
Now it works. I could often just put the definition above, or include the header which is needed, but I don't want to include headers in a header or juggle with the definition order, it always gets messy.
The solution I showed usually works, but now I have encountered a new phenomenon. This time the datatype is not a class but a typedef, I cant use prototypes for a typedef and I don't want to use the actual datatype which the typedef incorporates.. it's messy too.
Is there any solution to this?
Firstly, the solution you've thought of (prototype and pointer), is unneeded, and slower than just implementing it without the pointer.
The "proper" solution for this, would be creating seperate headers for each type, and then include them in your other header. That way it will always be defined! You can even make them so that they include eachother.
However, if you've ever opened a .h file provided by g++, you've most likely seen this at the start of the header:
#ifndef SOMETHING_H
#define SOMETHING_H
// Code
#endif /* SOMETHING_H */
This is to solve the issue of types redefining themselves.
If they weren't there, and you included the header file multiple times, the types would be redefined, and an error would be thrown. This makes it so that the types are always present, but never included twice.
I hope that helps!
Place each class/type in it's own header file, and then include the relevant header file in other headers where you need it. Use an inclusion guard in each header e.g.:
// SomeHeaderFile.h
#ifndef SOME_HEADER_FILE_H
#define SOME_HEADER_FILE_H
// code
#endif
I disagree that this is messy - it allows you have an organised structure to you project, it allows each class to operate independently of others and without worrying about order, and it's a good idea to place each class in it's own file anyway.
You could just define the class inside the other class like
template<class T>
class vertex {
private:
class edge {
public:
vertex<T> *to;
double weight;
edge() {
weight = INFINITY;
to = NULL;
};
} *paths;
T data;
unsigned nof_paths;
public:
vertex(T val) {
data = val;
paths = NULL;
nof_paths = 0;
}
void addPathTo(vertex<T>*&);
edge* getAllPaths() {
return paths;
};
};
Obviously this works for small classes... if your class is ENORMOUS you'll be better using separate header files like the other guys said.