I am working on a self organizing map program.
For it i am trying to create a way that I can centralize all the user/developer variables that can be set. I have been trying to use a Config.h/.cpp files but am unsure if this is the correct/best method.
It seems if I don't put things in in just the right way it errors on compile.
The question is the best/correct way to centralize variables that must be changed in between compilation and runs?
Config.h
#ifndef CONFIG_H_
#define CONFIG_H_
class Config{
public:
static const std::string outputFileLocation;//
static const std::string inputFilename;//
static const std::string outputFileExt;//
unsigned int vectorLength = 3;//RGB
//VARIBLE USED IN SOM CLASS
static const int NODE_GRID_HEIGHT = 100;
static const int NODE_GRID_WIDTH = 100;
};
#endif /* CONFIG_H_ */
Config.cpp
#include "Config.h"
//location to store output soms at it is iterated through
std::string Config::outputFileLocation = "/home/projectFiles/testMedia/results/mySom_";
//extension to put on output soms.
std::string Config::outputFileExt = ".jpeg";
////starting rgb image file to proccess
std::string Config::inputFilename = "/home/projectFiles/testMedia/yellowColor3.jpg";
////Length of muliti-dimensional data point. ie. a pixel.
unsigned int Config::vectorLength = 3;
It's a valid approach to keep the config in a distinct class. So you will be able to define a constructor for a default configuration, as well as config load and save methods.
However in you code there are minor consistency issues.
If you declare :
static const std::string outputFileLocation; // you said const
Then you should define it as a const :
const std::string Config::outputFileLocation = "/home/projectFiles/testMedia/results/mySom_";
Conversely, if you define a non static data member:
unsigned int vectorLength = 3; //You already intialise it here
You shall not redefine it as you did. This would only be necessary for statics.
However, I wonder why you make the statics const. This requires that they are initialised (either as you did, if they are static, or as part of the constructor for ordinary members) and they may not change afterwards. This prevents your from changing the configuration, for example when loading a config file at startup.
Additional thoughts
Once you have your configuration class, you can decided easily which variable is fixed at compilation, and which should be initialised dynamically. Dynamically could for example be:
read a configuration file (see: this SO question).
get some variables through system environment (see getenv())
system specific approaches, but this woudld not be portable so should be considered with care (for windows, it's usual for example to use the registry)
using command line arguments passed to main().
I deduce you are using your code to run experiments, since you need to change variables values between compilations and runs. One simple way I have done this in the past is by centralizing everything inside an unnamed namespace in a header file. This way, you may drop the static declarations, and just #include the config file where you need.
Something like this.
Configs.h
#ifndef CONFIG_H_
#define CONFIG_H_
namespace{
const std::string outputFileLocation = "something";//
const std::string inputFilename = "something";//
const std::string outputFileExt = "something";//
unsigned int vectorLength = 3;//RGB
//VARIBLE USED IN SOM CLASS
const int NODE_GRID_HEIGHT = 100;
const int NODE_GRID_WIDTH = 100;
};
#endif
Note this might not be the best solution, but is simple and effective. Depending on the goals of your project, you might need to consider a more elegant solution.
Another suggestion
Assuming my deduction is correct, reading those values from a configuration text file would also be a good option. You would not need to recompile between runs, which may be very time consuming if you have a large project, and many other files depend on that single configuration one.
Related
I have a C++20 program where the configuration is passed externally via JSON. According to the “Clean Architecture” I would like to transfer the information into a self-defined structure as soon as possible. The usage of JSON is only to be apparent in the “outer ring” and not spread through my whole program. So I want my own Config struct. But I am not sure how to write the constructor in a way that is safe against missing initializations, avoids redundancy and also separates the external library from my core entities.
One way of separation would be to define the structure without a constructor:
struct Config {
bool flag;
int number;
};
And then in a different file I can write a factory function that depends on the JSON library.
Config make_config(json const &json_config) {
return {.flag = json_config["flag"], .number = json_config["number"]};
}
This is somewhat safe to write, because one can directly see how the struct field names correspond to the JSON field. Also I don't have so much redundancy. But I don't really notice if fields are not initialized.
Another way would be to have a an explicit constructor. Clang-tidy would warn me if I forget to initialize a field:
struct Config {
Config(bool const flag, int const number) : flag(flag), number(number) {}
bool flag;
int number;
};
And then the factory would use the constructor:
Config make_config(json const &json_config) {
return Config(json_config["flag"], json_config["number"]);
}
I just have to specify the name of the field five times now. And in the factory function the correspondence is not clearly visible. Surely the IDE will show the parameter hints, but it feel brittle.
A really compact way of writing it would be to have a constructor that takes JSON, like this:
struct Config {
Config(json const &json_config)
: flag(json_config["flag"]), number(json_config["number"]) {}
bool flag;
int number;
};
That is really short, would warn me about uninitialized fields, the correspondence between fields and JSON is directly visible. But I need to import the JSON header in my Config.h file, which I really dislike. It also means that I need to recompile everything that uses the Config class if I should change the way that the configuration is loaded.
Surely C++ is a language where a lot of boilerplate code is needed. And in theory I like the second variant the best. It is the most encapsulated, the most separated one. But it is the worst to write and maintain. Given that in the realistic code the number of fields is significantly larger, I would sacrifice compilation time for less redundancy and more maintainability.
Is there some alternative way to organize this, or is the most separated variant also the one with the most boilerplate code?
I'd go with the constructor approach, however:
// header, possibly config.h
// only pre-declare!
class json;
struct Config
{
Config(json const& json_config); // only declare!
bool flag;
int number;
};
// now have a separate source file config.cpp:
#include "config.h"
#include <json.h>
Config::Config(json const& json_config)
: flag(json_config["flag"]), number(json_config["number"])
{ }
Clean approach and you avoid indirect inclusions of the json header. Sure, the constructor is duplicated as declaration and definition, but that's the usual C++ way.
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;
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 :)
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.
I want to declare string constants that will be used across various classes in the project. I am considering two alternatives
Option 1:
#header file
class constants{
static const string const1;
};
#cpp file
const string constants::const1="blah";
Option 2:
#header file
namespace constants{
static const string const1="blah";
};
Just wondering what would be a better implementation.
Already looked at
Where to store Class Specific named constants in C++
Where to put constant strings in C++: static class members or anonymous namespaces
UPDATE:
Option 3:
Based on the suggestions from "potatoswatter" and "sellibitze" i currently have the following implementation?
#header file
namespace constants{
extern const string& const1(); //WORKS WITHOUT THE EXTERN ***WHY***
};
#cpp file
namespace constants{
const string& const1(){static string* str = new string ("blah"); return *str;}
}
I'm including the header file where i need to use the constants. Are there any major cons of this implementation?
Update 2 years later:
Every global accessible by more than one source file should be wrapped in an inline function so the linker shares the object between the files, and the program initializes it properly.
inline std::string const &const1() {
static std::string ret = "hello, world!";
return ret;
}
The inline function is implicitly extern and may be wrapped in a named namespace or a class, if you like. (But don't use a class just to hold static members, as namespaces are better for that. And don't use an anonymous namespace as that would defeat the linker, and each source would see a different std::string object.)
All answers that resort to std::string run the risk of dynamically allocating memory for a string literal which is going to remain constant throughout the lifetime of the program (and the binary), so they should be avoided.
sellibitze's answer comes close but it has the problem of declaring it once and then defining it elsewhere, which I don't find elegant and is more work. The best way would be
namespace constants {
const char * const blah = "blah!"
const char * const yada = "yada yada!"
}
This is solution is discussed further here.
Neither. I'd go with this:
// header file
namespace constants {
extern const char const1[];
}
// cpp file
namespace constants {
extern const char const1[] = "blah";
}
The header file contains a declaration of const1 with incomplete type but convertible to char const* and the cpp-file contains a definition of the character array with external linkage. There is no dynamic initialization like you have with std::string. So, that's a plus, IMHO.
Option 1 achieves the same as Option 2, but in a messier way.
If you're going to use a class that just has static members, especially for global access/constants, use a namespace.