0

Abstractly, say you were building a physics simulation and needed many universal constants or typical values for things like mass. It feels like there should be a standard approach to implementing this? I'm mainly a hobbiest, using C++, and I can think of ways it can be done but unsure what should be done, and I'm worried I'd hit some messy pitfall.

So if you had constants like g, G, pi, alpha, e, h, h-bar etc and lots of values like "Typical Star: Mass = 1 MSolar, wavelength = 600nm" and so on. how would you implement them and potentially group and organise them in a way thats efficient?

I was considering just a header file with the values as either #define macros, or consts, maybe even a std::map, but that feels like adding a lot of global variables in a way that would quickly get out of hand. Is it just something to endure or are there cleaner ways?

Tess
  • 3
  • 1
  • 1
    https://en.cppreference.com/w/cpp/header/numbers for a few pre-defined constants. – sweenish May 02 '23 at 19:36
  • do not use macros, other approaches sound ok. If you want global constants, then adding lots of global constants is just fine. It is mutable global state that is bad. – 463035818_is_not_an_ai May 02 '23 at 19:36
  • 2
    *but that feels like adding a lot of global variables in a way that would quickly get out of hand* -- If they are declared within a namespace, struct, or class, and they are `const`, `constexpr`, etc., then there is little that would get "out-of-hand". It is the macro and/or the old school "`extern` in all modules except for one" approach that will get out of hand with a lot of globals. – PaulMcKenzie May 02 '23 at 19:43
  • Put them in a namespace. Probably you want to duplicate in c++ python's scipy.constants (https://docs.scipy.org/doc/scipy/reference/constants.html) – lastchance May 02 '23 at 19:47

3 Answers3

1

The C++ way of doing this is to have them as inline constexpr variables in a header file. That's what the standard does with some constants. You can define yours:

namespace Constants {
inline constexpr auto goldenRatio = 1.61803398875;
// ...
};
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • note these are just global variables, as there's not much difference between writing `Constants::goldenRatio` and `Constants_goldenRatio`, except for the convenience of `using namespace` – user253751 May 02 '23 at 20:42
0

Some of these already exist in the standard library and it may be a good idea to follow the approach that the standard library uses to implement more of them.

See https://en.cppreference.com/w/cpp/numeric/constants, for example an implementation for Euler's number looks (slightly simplified) like this in C++20 (in the namespace std::numbers for the standard library, but you should of course use your own):

// variable template for floating point types
template<std::floating_point T> constexpr T e_v = /* value of constant as a literal as precise as possible/neccessary */;

// short-hand for the double case
inline constexpr double e = e_v<double>;

And then one can use std::numbers::e for Euler's number as a double or std::numbers::e_v<float> for Euler's number as a float, and so on.

user17732522
  • 53,019
  • 2
  • 56
  • 105
0

In C++20 many mathematical numeric constants can be included via #include <numbers>. Beyond that in C++, don't use #define, prefer either

constexpr double pi = 3.14159265358979323846;

or

const double pi = 3.14159265358979323846;

The main advantage of using constexpr over const is that constexpr guarantees that the value of the constant is computed at compile time, whereas const only guarantees that the value is not modified at runtime. This means that constexpr constants can be used in contexts where a compile-time constant expression is required, such as in array sizes or template arguments, although typically this kind of usage is more applicable to integer constants.

jwezorek
  • 8,592
  • 1
  • 29
  • 46