C++ Best practices for constants - c++

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.

Related

How can I minimize both boilerplate and coupling in object construction?

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.

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;

Creating a centralized variable file

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.

C++: is there a point to having a header file? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ - What should go into an .h file?
I know this is general, but I find it really annoying coding things twice, and would find it a lot easier if I didn't have to browse between two files (my .h and .cc) rather than just keep it all in one.
So, what is the point in having a header file if most of what is there must be rewritten and the rest can just be placed in the .cc.
Instead of:
class VoterData {
// raw data
Voter::States state;
bool vote;
unsigned int numBlocked;
// flags
bool _hasState, _hasVote, _hasNumBlocked;
public:
VoterData();
void reset();
// getters
Voter::States getState();
bool getVote();
unsigned int getNumBlocked();
bool hasState();
bool hasVote();
bool hasNumBlocked();
// setters
void setState(Voter::States state);
void setVote(bool vote);
void setNumBlocked(unsigned int numBlocked);
};
AND:
/* VoterData */
VoterData::VoterData() {
reset();
}
void VoterData::reset() {
_hasState = _hasVote = _hasNumBlocked = false;
}
// getters
Voter::States VoterData::getState() { return state; }
bool VoterData::getVote() { return vote; }
unsigned int VoterData::getNumBlocked() { return numBlocked; }
bool VoterData::hasState() { return _hasState; }
bool VoterData::hasVote() { return _hasVote; }
bool VoterData::hasNumBlocked() { return _hasNumBlocked; }
// setters
void VoterData::setState(Voter::States state) {
this->state = state;
_hasState = true;
}
void VoterData::setVote(bool vote) {
this->vote = vote;
_hasVote = true;
}
void VoterData::setNumBlocked(unsigned int numBlocked) {
this->numBlocked = numBlocked;
_hasNumBlocked = true;
}
Why shouldn't I just put it all in the .cc file and declare the class there?
C++ doesn't tell you where to put your code. Actually, in your case it might be better to use one file:
struct VoterData {
// raw data
Voter::States state;
bool vote;
unsigned int numBlocked;
// flags
bool _hasState, _hasVote, _hasNumBlocked;
// No getters, setters and other cruft needed
};
If your class is more complicated than my or your example, you will notice that having a header file gives an advantage in understanding your program.
In that case, the header file (x.h) will be small (e.g. 20 lines of code) and the implementation file (x.cc) will be large (e.g. 200 lines of code - much more than in your example class). Anyone (who wants to understand what the class does, or how to use it) has to look at the 20 lines in the header file and doesn't have to look at the 200 other lines of code - that's great (speaking from experience)!
So, your example doesn't require separation into header and implementation files.
I believe there are a lot of reasons, which the most noticeable ones are:
If you put a class in a source file and then include that source file in other source files that use that it will work, but it won't work if anything is outside of the class.
There is a huge speedup if other source files that use the class include only header files and don't have to parse the whole class source file.
Circular references, if class A uses class B and class B uses class A, you have to use header files, its not possible with only source files (there is a possible workaround with templates but its just complicated and will get you into trouble).
Of course you can put EVERYTHING in a single .cc file and make it compiled & run, no matter how many classes there are.
Whether to use header files depends on your purpose and habits.
For example, if you want to write a shared library and release it to others, you have to use header files. The users can then include your header files and call the functions you wrote.
For most any one-off code—which will never be shared with any other programs or persons—then I agree: skip creating a header file and put all the code in a .C, .cc, .c++, etc. file
However, if a class will/should/might be reused—often the goal of much development intent—somewhere along the way it is a great idea to identify the declaration portion and put that in a header file, and the implementation part and put that in a source mode: eventually it may become a shareable library.
If everything is in the .cc file and your compiler treats that file as a compilation unit, then you will not be able to use the classes defined in that file in other files (you will get a multiply defined symbol error). Also defining everything in a single file will significantly increase your compilation times, especially in a large project.
All of the answers so far seem to answer with respect to how the language works according to the specification and current compilers, but I think the question is about why it is designed that way.
When you add a method to a class, you have to put the declaration in two places, wasting programming time. It should be entirely possible to add a compiler pass that generates header files based on their code files, shouldn't it? Slightly longer compile times seems like an okay trade-off nowadays, but it wasn't always so.
One thing the current system does is give you finer control over what is where. There may be some defines for example that you want to have for your code that you don't want to be put into the header for anyone that calls your class.

Proper way to make a global "constant" in C++

Typically, the way I'd define a true global constant (lets say, pi) would be to place an extern const in a header file, and define the constant in a .cpp file:
constants.h:
extern const pi;
constants.cpp:
#include "constants.h"
#include <cmath>
const pi=std::acos(-1.0);
This works great for true constants such as pi. However, I am looking for a best practice when it comes to defining a "constant" in that it will remain constant from program run to program run, but may change, depending on an input file. An example of this would be the gravitational constant, which is dependent on the units used. g is defined in the input file, and I would like it to be a global value that any object can use. I've always heard it is bad practice to have non-constant globals, so currently I have g stored in a system object, which is then passed on to all of the objects it generates. However this seems a bit clunky and hard to maintain as the number of objects grow.
Thoughts?
It all depends on your application size. If you are truly absolutely sure that a particular constant will have a single value shared by all threads and branches in your code for a single run, and that is unlikely to change in the future, then a global variable matches the intended semantics most closely, so it's best to just use that. It's also something that's trivial to refactor later on if needed, especially if you use distinctive prefixes for globals (such as g_) so that they never clash with locals - which is a good idea in general.
In general, I prefer to stick to YAGNI, and don't try to blindly placate various coding style guides. Instead, I first look if their rationale applies to a particular case (if a coding style guide doesn't have a rationale, it is a bad one), and if it clearly doesn't, then there is no reason to apply that guide to that case.
I can understand the predicament you're in, but I am afraid that you are unfortunately not doing this right.
The units should not affect the program, if you try to handle multiple different units in the heart of your program, you're going to get hurt badly.
Conceptually, you should do something like this:
Parse Input
|
Convert into SI metric
|
Run Program
|
Convert into original metric
|
Produce Output
This ensure that your program is nicely isolated from the various metrics that exist. Thus if one day you somehow add support to the French metric system of the 16th century, you'll just add to configure the Convert steps (Adapters) correctly, and perhaps a bit of the input/output (to recognize them and print them correctly), but the heart of the program, ie the computation unit, would remain unaffected by the new functionality.
Now, if you are to use a constant that is not so constant (for example the acceleration of gravity on earth which depends on the latitude, longitude and altitude), then you can simply pass it as arguments, grouped with the other constants.
class Constants
{
public:
Constants(double g, ....);
double g() const;
/// ...
private:
double mG;
/// ...
};
This could be made a Singleton, but that goes against the (controversed) Dependency Injection idiom. Personally I stray away from Singleton as much as I can, I usually use some Context class that I pass in each method, makes it much easier to test the methods independently from one another.
A legitimate use of singletons!
A singleton class constants() with a method to set the units?
You can use a variant of your latter approach, make a "GlobalState" class that holds all those variables and pass that around to all objects:
struct GlobalState {
float get_x() const;
float get_y() const;
...
};
struct MyClass {
MyClass(GlobalState &s)
{
// get data from s here
... = s.get_x();
}
};
It avoids globals, if you don't like them, and it grows gracefully as more variables are needed.
It's bad to have globals which change value during the lifetime of the run.
A value that is set once upon startup (and remains "constant" thereafter) is a perfectly acceptable use for a global.
Why is your current solution going to be hard to maintain? You can split the object up into multiple classes as it grows (one object for simulation parameters such as your gravitational constant, one object for general configuration, and so on)
My typical idiom for programs with configurable items is to create a singleton class named "configuration". Inside configuration go things that might be read from parsed configuration files, the registry, environment variables, etc.
Generally I'm against making get() methods, but this is my major exception. You can't typically make your configuration items consts if they have to be read from somewhere at startup, but you can make them private and use const get() methods to make the client view of them const.
This actually brings to mind the C++ Template Metaprogramming book by Abrahams & Gurtovoy - Is there a better way to manage your data so that you don't get poor conversions from yards to meters or from volume to length, and maybe that class knows about gravity being a form acceleration.
Also you already have a nice example here, pi = the result of some function...
const pi=std::acos(-1.0);
So why not make gravity the result of some function, which just happens to read that from file?
const gravity=configGravity();
configGravity() {
// open some file
// read the data
// return result
}
The problem is that because the global is managed prior to main being called you cannot provide input into the function - what config file, what if the file is missing or doesn't have g in it.
So if you want error handling you need to go for a later initialization, singletons fit that better.
Let's spell out some specs. So, you want:
(1) the file holding the global info (gravity, etc.) to outlive your runs of the executable using them;
(2) the global info to be visible in all your units (source files);
(3) your program to not be allowed to change the global info, once read from the file;
Well,
(1) Suggests a wrapper around the global info whose constructor takes an ifstream or file name string reference (hence, the file must exist before the constructor is called and it will still be there after the destructor is invoked);
(2) Suggests a global variable of the wrapper. You may, additionally, make sure that that is the only instance of this wrapper, in which case you need to make it a singleton as was suggested. Then again, you may not need this (you may be okay with having multiple copies of the same info, as long as it is read-only info!).
(3) Suggests a const getter from the wrapper. So, a sample may look like this:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>//for EXIT_FAILURE
using namespace std;
class GlobalsFromFiles
{
public:
GlobalsFromFiles(const string& file_name)
{
//...process file:
std::ifstream ginfo_file(file_name.c_str());
if( !ginfo_file )
{
//throw SomeException(some_message);//not recommended to throw from constructors
//(definitely *NOT* from destructors)
//but you can... the problem would be: where do you place the catcher?
//so better just display an error message and exit
cerr<<"Uh-oh...file "<<file_name<<" not found"<<endl;
exit(EXIT_FAILURE);
}
//...read data...
ginfo_file>>gravity_;
//...
}
double g_(void) const
{
return gravity_;
}
private:
double gravity_;
};
GlobalsFromFiles Gs("globals.dat");
int main(void)
{
cout<<Gs.g_()<<endl;
return 0;
}
Globals aren't evil
Had to get that off my chest first :)
I'd stick the constants into a struct, and make a global instance of that:
struct Constants
{
double g;
// ...
};
extern Constants C = { ... };
double Grav(double m1, double m2, double r) { return C.g * m1 * m2 / (r*r); }
(Short names are ok, too, all scientists and engineers do that.....)
I've used the fact that local variables (i.e. members, parameters, function-locals, ..) take precedence over the global in a few cases as "apects for the poor":
You could easily change the method to
double Grav(double m1, double m2, double r, Constants const & C = ::C)
{ return C.g * m1 * m2 / (r*r); } // same code!
You could create an
struct AlternateUniverse
{
Constants C;
AlternateUniverse()
{
PostulateWildly(C); // initialize C to better values
double Grav(double m1, double m2, double r) { /* same code! */ }
}
}
The idea is to write code with least overhead in the default case, and preserving the implementation even if the universal constants should change.
Call Scope vs. Source Scope
Alternatively, if you/your devs are more into procedural rather thsn OO style, you could use call scope instead of source scope, with a global stack of values, roughly:
std::deque<Constants> g_constants;
void InAnAlternateUniverse()
{
PostulateWildly(C); //
g_constants.push_front(C);
CalculateCoreTemp();
g_constants.pop_front();
}
void CalculateCoreTemp()
{
Constants const & C= g_constants.front();
// ...
}
Everything in the call tree gets to use the "most current" constants. OYu can call the same tree of coutines - no matter how deeply nested - with an alternate set of constants. Of course it should be encapsulated better, made exception safe, and for multithreading you need thread local storage (so each thread gets it's own "stack")
Calculation vs. User Interface
We approach your original problem differently: All internal representation, all persistent data uses SI base units. Conversion takes place at input and output (e.g. even though the typical size is millimeter, it's always stored as meter).
I can't really compare, but worksd very well for us.
Dimensional Analysis
Other replies have at least hinted at Dimensional Analysis, such as the respective Boost Library. It can enforce dimensional correctness, and can automate the input / output conversions.