Where to put global domain specific constants (and how)? - c++

I have a C++ code that's a physics simulation tool.
I would like to store some physical constants, conversion factor between different sets of units, and also some more application specific constants (such as definition like enum Planes {X=0, Y=1}) and I would like to be able to access them from everywhere in my code.
What would be the best way to do that ?
I think one way would be to create a namespace namespace constants (which can then be a nested namespace in my main namespace) with nested namespaces (like 'constants', 'units', etc.).
Would it be the way you would do that ?
If I use that method, do I have to make it a header file and include it everywhere ?
If I understand correctly the variables in the namespace at global scope have static linkage, but no external linkage. Then if I want to use them without including a file, I also have to declare them extern ?
As you can see I am a bit confused about that...

Namespace constants are the way to go in most cases.
If I use that method, do I have to make it a header file and include it everywhere ?
Yes, or not everywhere but only where it's really USED.
If I understand correctly the variables in the namespace at global scope have static linkage, but no external linkage. Then if I want to use them without including a file, I also have to declare them extern ?
Yes, you have to do it that way :
// header
namespace modulename
{
// maybe add another namespace to specify that you have constants, but taste-dependant
namespace domain // like maths or physics
{
extern const Number THIS_NUMBER; // have to be defined in the cpp
extern const int THAT_NUMBER = 256; // if it's int-based type, you can define it -here - BUT DON'T IF IT CAN BE CHANGED : all files including this one would have to be recompiled at each value change!!
}
}
// .cpp, where you have the definitions
namespace modulename
{
namespace domain // like maths or physics
{
const Number THIS_NUMBER = Number( 256.42f ); // definition - static is implicit
}
}

If the compiler doesn't say anything about it being unrecognized then you are safe. All that matters is that the compiler knows where to find the variable. Once you include the header file, it is technically a copy and paste of the code in that file. Given this, you need to do some precompiler directives.
#ifndef _MYGLOBALS
#define _MYGLOBALS
int global_integer;
long global_long;
#endif
This ensures that they will only be included once, and you will not have many references of the variables in your code.

I'd make a constants namespace and put in all globally-relevant constants there. Any constants only relevant to a single class, declare as static consts within the class itself.

Related

Scope of a static variable to several files C++ [duplicate]

Well, I'm learning C++ and never really learned how to do stuff that is not OO.
I'm trying to get a bit more experience coding in C style.
GobalInformation.h
#pragma once
#ifndef GLOBALINFORMATION_H
#define GLOBALINFORMATION_H
#include "MapInformation.h"
namespace gi {
MapInformation mapInf;
};
#endif
I would like to be able to access gi::mapInf from every header and cpp in my project. Right now I'm including globalinformation.h in every header, so I'm getting linker errors with multiple definitions.
How can I work around the problem?
In header file only do
namespace gi {
extern MapInformation mapInf;
};
In CPP file provide the actual definition.
namespace gi {
MapInformation mapInf;
};
It will work as you intend.
If you are using the MapInformation across dynamic link library boundaries you might have to link against the library that includes the definition cpp file. Also on Window you might have to use dllimport/dllexport
Be aware that having globals in multiple compilation units can easily lead to order-of-initialization problems. You may wish to consider replacing each global with a function that returns a reference. In your case, put this in one cpp file and declare it in the header:
namespace gi {
MapInformation& getMapInf()
{
static MapInformation result;
return result;
}
}
Global variables are C, but namespaces are C++. There is a good discussion on using global variables and how they can be replaced by Singleton pattern: Globals and Singletons
And here is a simple sample: CPP/Classes/Singleton
Perhaps a better solution is to create a global object that contains all your global data. Then pass a smart pointer to the classes that actually need to access this shared global data.
Example:
class GlobalData
{
public:
int ticks_;
};
//Other file
class ThatNeedsGlobalData
{
public:
ThatNeedsGlobalData(std::shared_ptr<GlobalData> globalData);
};
This will save you some trouble.
Good luck!
Here are a few things that you need to take care of while trying to use global variables the way you have used.
Ensure that all the header files that the header files that GobalInformation.h includes are also enclosed insides #ifndefs. (I could not see mapinformation.h so I assume you have done it)
Just like CPP, C compiler also does not ensure order of the initialization of variables in different translation units(different C/CPP files).
Hence declare the header file as
//GlobalInformation.h
namespace gi {
extern MapInformation mapInf;
};
In a function that you know would be called first initialize the variable. This way lazy-initialization can also be acheived in C.

Using namespaces and includes

The question might be trivial (and possibly a duplicate).
As far as I understand, a C/C++ header file (with a using namespace in it), when used by other source files, it is copied right at the point where the #include directive was in that source file.
Also, given that a source file uses a relatively large number of include directives and that there may be a couple of "redefinitions" for the entire standard library (simply targeted at different implementations).
Here is the main question: How do I know which namespaces am I currently using at any point in the source file if the source file has no using namespace statement?
I'm reading through source files and I have no idea which namespace is being used.
One can override the namespace cleverness by using something like ::std::getline().
If there is no easy way of determining the namespace, is it fair to refactor those files, such that where say string is used to replace it with ::std::string?
If you don't have a using namespace ... directive you're not using any namespace. In general, your code should refer to things in the standard library with their full names, e.g., std::cout, std::get_line(), std::string.
Yes, you can save your self some typing at the expense of loss of clarity and sometimes mysterious compilation failures or, worse, runtime failures with using namespace std;. After that, you don't have to put std:: in front of the names of things in the standard library: cout, get_line(), string. The using directive puts those names into the global namespace, along with a bunch of sludge that you probably aren't interested in.
If you use something like using namespace std; it should appear only in a source file, never in a header. That way you can tell which namespaces have been "used" by looking at the top of the file. You shouldn't have to track through all your headers for stray using directives.
using namespace does not mean that you currently use this specific namespace. It means, that all types, variables and functions from this namespace are now in your global namespace, for this translation unit. So, you might have multiple of these statements.
This is why header files should never use using namespace. There is no easier way than using std::string within a header file, you should always be very explicit about the namespace without using namespaces.
Having used using namespace xxx, there is no way of finding out that xxx is now in global namespace, I am afraid.
using namespace does not do what you expect...
If you want to place functions, classes or variables in a namespace, you do it this way:
namespace foo
{
void f();
}
namespace bar
{
void f();
}
This declares two functions f in namespaces foo and bar respectively. The same you will find in header files; if there is no namespace specified as above, then the function/class/variable is in global namespace. Nothing more.
using namespace now allows you to use functions from a namespace without having to specify it explicitly:
// without:
foo::f();
bar::f();
f(); // unknown!
using namespace foo;
foo::f(); // still fine...
bar::f();
f(); // now you call foo::f
Be aware that this is bad practice, though (the link refers to namespace std, but same applies for all namespaces).
This is even worse in header files: there is no way to undo the effect of a declared using namespace <whatever> again – so you impose it on all users of your header, possibly causing great trouble to some of them. So please don't ever use it in header files.
There are three approaches I can think of right now:
Use the IDE: A modern development environment should be able (possibly with the help of plug-ins) to analyze your code while you edit, and tell you the authoritative qualified name of any identifier you hover the mouse cursor over.
Of course this is not an option if you are not using an IDE, and sometimes even IDEs may get confused and give you wrong information.
Use the compiler and guesswork: If you already have a hunch which namespace you might be in, you can define some object, reference it via qualified name, and see if the code compiles, like so:
const int Fnord = 1;
const int* Probe = &::solid::guess::Fnord;
One caveat is that it may give misleading results if using namespace or anonymous namespaces are involved.
Use the preprocessor: Most compilers define a preprocessor macro that tells you the name of the function it is used in, which may include the namespace; for example, on MSVC, __FUNCTION__ will do just this. If the file contains a function that you know will be executed, you can have that function tell you its authoritative qualified name at run-time, like so:
int SomeFunction(void)
{
printf("%s\n", __FUNCTION__);
}
If you can't use standard output, you might store the value in a variable and use a debugger to inspect it.
If you can find no such function, try defining a class with a static instance of itself, and placing the code in the constructor.
(Unfortunately I can't think of a way to inspect the macro's value at compile-time; static_assert came to my mind, but it can't be used inside functions, and __FUNCTION__ can't be used outside.)
The macro is not standardized though, and may not include the namespace (or it may not exist at all). On GCC for instance, __FUNCTION__ will only give you the unqualified name, and you will have to use __PRETTY_FUNCTION__ instead.
(As of C99 and C++11 there does exist a standardized alternative, __func__, but the format of the function name is unspecified, and may or may not include the namespace. On GCC it does not.)

Merits of defining constants in header or implementation files

Throughout a C++ codebase I'm working in, the pattern for declaring constants looks something like this.
// module_constants.h
#ifndef MODULE_CONSTANTS
#define MODULE_CONSTANTS
namespace module {
extern const int SOME_CONST;
}
#endif
// module_constants.cpp
#include "module_constants.h"
namespace module {
const int SOME_CONST = 1;
}
What are the merits of this approach rather than defining all of the constant values in the header?
The single advantage I know of is that you only have to recompile a single cpp-file when you change the constant’s value and not every file that directly or indirectly includes the header file.
That can be particularly useful when you provide a dynamically linked library and want to patch it without recompiling the actual application.
Some drawbacks are that
(as latedeveloper wrote) you can't use them at places where a constant expression is required (e.g. array bounds or template parameters) outside of the cppfile, in which you defined it.
you make the optimizer's life harder.
from a tooling perspective e.g. intellisense won't show you it's value.
Well, by putting it in the header you'd run into the one-definition rule if you include it in more than one cpp file.
But, on the other hand, you can create it as a constexpr in the header I believe.

#includes within a namespace, to "embed" prewritten stuff in namespace

BRIEF: is it ever safe to do
namespace Foo {
#include "bar"
}
Before you blithely say no, I think I have some rules that allow it fairly safely.
But I don't like them, since they require the includer to separately include all global scope headers needed. Although this mightr be tolerable, if we imagine including within a namespace to be just a special management feature.
And overall, externs and forward declarations just don't work well from within namespaces.
So I gues I am asking
a) What other gotchas
b) is there a better way
== A [[Header-only library]] ==
I like writing libraries. [[Header-only libraries and linker libraries]].
E.g.
#include "Valid.hpp"
defines a template Valid, for a simple wrapper type.
(Don't get bogged down in "You should use some standard library for this rather than your own. This is an exanple. I dunno if Boost or C++ have yet standardized this. I have been using wrappers since templates were added to C++.)
Also, let us say, it is a header only library, that defines, in Valid.hpp,
a print function
std::string to_string( const Valid& v ) {
std::ostringstream oss;
if( v.valid() ) { oss << v; }
else { "invalid"; }
return oss.str();
}
And because I think it is the right thing to do,
I have Valid.hpp include the headers it depends on:
Valid.hpp:
#include <iostream>
#include <sstream>
template<typename T>
class Valid {
private:
T value_;
bool valid_
...
};
...
std::string to_string( const Valid<T>& v ) { ...
So far, so good.
I can use Valid straightforwardly.
== Name collision - trying to use include within namespace to work around ==
But sometimes there is a collision.
Sometimes somebody else has their own Valid.
Namespaces to the rescue, right? But I don't want to change all of my existing code to use the namespace.
So, I am tempted, in a new project that has a collision, to do
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
PROBLEM: the headers included are no longer freestanding. Everything defined inside is no placed inside
namespace AG::Wrapper.
It's not hard to "fix".
Al we "must" do is include all the top level libraries that Valid.hpp depends on.
If they have include guards, they will not be re-included.
#include <iostream>
#include <sstream>
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
But it is no longer freestanding. :-(
Worse, sometimes the header-only library contains extern declarations and forward declarations of stuff outside itself.
These declarations get placed inside the namespace too.
In particular, if the extern declarayion is inside a function defined in the namespace.
I.e. sometimes we use extern and forward declarations, rather than included an entire header file.
These get included in the namespace.
Q: is there a better way?
== :: doesn't do it ==
Hint: :: doesn't do it. At least not all the time, not in gcc 4.7.2.
(Gcc's behavior in this has changed over time. Gcc 4.1.2 behaved differently.)
E.g.
Type var;
namespace Foo {
void bar() {
extern ::Type ::var;;
extern ::Type ::Foo::bar;
extern ::Type::foo ::bar; // see the ambiguity?
};
But it's not just the ambiguity.
int var;
namespace Foo {
void bar() {
extern int var;
};
works - Foo::bar'svar is equal to ::var.
But it only works because of the declaration outside the namespace.
The following doesn't work
header
int var;
cpp
namespace Foo {
void bar() {
extern int var;
}
}
although the following does:
header
int var;
cpp
void bar() {
extern int var;
}
}
Basically, what this amounts to saying is that
it is not a trivial refactoring to put functions inside a namespace.
Wrapping a namespace around a chunk of code,
whether or not it is #include'd,
is not a sufficient.
... at least not if there are extern or forward declarations.
And even if you
== Opinion against putting includes within namespaces ==
Stackoverflow folks seem to be against putting #includes inside namespaces:
E.g. How to use class defined in a separate header within a namespace:
... you should never write a #include inside a namespace. Where "never" means, "unless you're doing something really obscure that I haven't thought of and that justifies it". You want to be able to look at a file, and see what the fully-qualified names are of all the things in it. You can't do that if someone comes along later and sticks an extra namespace on the front by including from inside their namespace. – Steve Jessop Jan 6 '12 at 16:38
Overall question:
Is there any way, from deep within a namespace,
to say "and now here are some names that I am depending on from the outside world, not within the namespace."?
I.e. I would like to be able to say
namespace A {
void foo() {
// --- here is a reference to gloal scope extreren ...
I know this is an old question, but I want to give a more detailed answer anyway. Also, give a real answer to the underlying problem.
Here's just a few things that can go wrong if you include a header from within a namespace.
The header includes other headers, which are then also included from within the namespace. Then a different place also wants to include these headers, but from outside the namespace. Because the headers have include guards, only one of the includes actually goes in effect, and the actual namespace of the stuff defined in the headers suddenly subtly depends on the order you include other headers.
The header, or any of its included headers, expects to be in the global namespace. For example, standard library headers will very often (in order to avoid conflicts) refer to other standard stuff (or implementation details) as ::std::other_stuff, i.e. expect std to be directly in the global namespace. If you include the header from within a namespace, that's no longer the case. The name lookup for this stuff will fail and the header will no longer compile. And it's not just standard headers; I'm sure there are some instances of this e.g. in the Boost headers too.
If you take care of the first problem by ensuring that all other headers are included first, and the second problem by making sure no fully qualified names are used, things can still go wrong. Some libraries require that other libraries specialize their stuff. For example, a library might want to specialize std::swap, std::hash or std::less for its own type. (You can overload std::swap instead, but you can't do that for std::hash and std::less.) The way to do this is close your library-specific namespace, open namespace std, and put the specialization there. Except if the header of the library is included in arbitrarily deeply nested namespaces, it cannot close those namespaces. The namespace std it attempts to open won't be ::std, but ::YourStuff::std, which probably doesn't contain any primary template to specialize, and even if it did, that would still be the wrong thing to do.
Finally, things in a namespace simply have different names than things outside. If your library isn't header-only but has a compiled part, the compiled part probably didn't nest everything in the namespace, so the stuff in the library has different names than the stuff you just included. In other words, your program will fail to link.
So in theory, you can design headers that work when included within a namespace, but they're annoying to use (have to bubble up all dependencies to the includer) and very restricted (can't use fully qualified names or specialize stuff in another library's namespace, must be header-only). So don't do it.
But you have an old library that doesn't use namespaces, and you want to update it to use them without breaking all your old code. Here's what you should do:
First, you add a subdirectory to your library's include directory. Call it "namespaced" or something like that. Next, move all the headers into that directory and wrap their contents in a namespace.
Then you add forwarding headers to the base directory. For each file in the library, you add a forwarder that looks like this:
#ifndef YOURLIB_LEGACY_THE_HEADER_H
#define YOURLIB_LEGACY_THE_HEADER_H
#include "namespaced/the_header.h"
using namespace yourlib;
#endif
Now the old code should just work the way it always did.
For new code, the trick is not to include "namespaced/the_header.h", but instead change the project settings so that the include directory points at the namespaced subdirectory instead of the library root. Then you can simply include "the_header.h" and get the namespaced version.
I don't think it's safe. You put all your includes into the namespace Foo...
Imagine some of your includes include something from the std namespace... I cannot imagine the mess !
I wouldn't do that.
Header files are not black boxes. You can always look at a header you're including in your project and see if it is safe to include it inside a namespace block. Or better yet, you can modify the header itself to add the namespace block. Even if the header is from a third-party library and changes in a subsequent release, the header you have in your project won't change.

How to make large numbers of existing functions available in the scope of a class?

I need to make a large (100's of source files) project into a library, removing dozens of global variables by putting them all into a class object.
The problem is the thousand or so functions that now need to be members of this class so they have access to the object variables.
Otehr than adding MyClass:: to every single function definition in the source files, is there a way to cheat and indicate that all the functions in a particular source file should be part of the MyClass scope?
Add all the globals to a namespace.
// MyGlobals.h
namespace MyGlobals
{
extern int g_i;
extern double g_d;
extern A g_A;
}
Whatever files you want to access, do:
using namespace MyGlobals;
inside the header file. In this (using namespace) way you can indicate that all the variables should be accessible without using scope resolution :: for that file. (i.e. you can simply access g_i instead of MyGlobals::g_i inside that file).
Also note that, you have to define all the global variables inside a .cpp file:
// MyGlobals.cpp
#include "MyGlobals.h"
int MyGlobals::g_i;
double MyGlobals::g_d;
A MyGlobals::g_A;