1

I always used #define to define magic numbers somewhere at the beginning of the the cpp file. I want to change that to const numbers. (globals declared / defined in the cpp file.) Is this a good idea? Should I put them into anonymous namespace? I never #include the cpp files anywhere.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Newline
  • 769
  • 3
  • 12
  • `constexpr` is better than `#define`, you can place them in unnamed namespace if used at file scope. – Jarod42 Sep 20 '18 at 14:09
  • Firstly, it's preferable to use a named namespace, secondly use constexpr. You could also make them static. – pointerless Sep 20 '18 at 14:09
  • 1
    Do not forget to make them not all uppercase. – Slava Sep 20 '18 at 14:15
  • @Slava What's wrong with uppercase for global / static consts? – Newline Sep 20 '18 at 14:25
  • 1
    @Newline they are uppercase because they are preprocessor macro, not because they are consts. Using compile time constants with uppercase symbols you actually increase risk of the problem and pattern was introduced originaly to avoid name conflict with preprocessor. But bad habits die hard – Slava Sep 20 '18 at 14:30
  • @pointerless They are in a named namespace already but within that I want to put them in anon namespace. Is that OK? You mean static class members or just static globals? Any difference between static constexpr int a = 0; and const int a = 0; if they are global? – Newline Sep 20 '18 at 14:30
  • @Newline `static` for global makes them visible only within compilation unit they are defined. This is old way, modern way is using anonymous namespace. – Slava Sep 20 '18 at 14:31
  • 2
    There's no point making them static or putting them in an anonymous namespace, const variables at namespace scope have internal linkage by default anyway (i.e. the `static` is implied). – Jonathan Wakely Sep 20 '18 at 15:21
  • 1
    @Newline [Stop the constant SHOUTING!](http://accu.org/index.php/articles/1923) – Jonathan Wakely Sep 20 '18 at 15:23

2 Answers2

5

Basically the only reason you have for choosing such #define "consts" is if the preprocessor itself will need to use them. Other than that, you have a whole heap of advantages for constexpr over using such #defines -- they are listed here.

Anonymous namespace are a good solution only if you're going to be using the magic numbers in the same file, as names inside it are never accessible from other translation units because the unnamed namespace has a unique identifier as far as the compiler is concerned. That said, There's no real gain here in putting the magic numbers inside an anonymous namespace, as either const or constexpr variables in any namespace scope inherently have internal linkage.

As far as the difference between const and constexpr goes in the context of objects, the gist is that while constexpr denotes a constant value known during compilation, const only denotes a constant value, that may not be known during compilation.1 This difference is crucial for compile-time programming, or for usage in other constant expressions.


1Do note that a const integral that is itself being initialized with a constant expression (such as an integer literal) as part of its declaration is implicitly a constant expression even without explicitly declaring it constexpr:

const int A = 50; // `A` is a constant expression

int n = 50;
const int B = n; // `B` is not a constant expression as it-
                 // is not being initialized with a constant expression
Geezer
  • 5,600
  • 18
  • 31
  • Does constexpr make a difference over const? – Newline Sep 20 '18 at 14:24
  • Note that certain "fastbuild" compilation tools will lump all of your C files together and your anonymous namespace might not be as unique as you'd expect. – Tim Randall Sep 20 '18 at 14:54
  • @TimRandall That's an eye opener friend, can you supply me with some sources so I'll add an appropriate edit? – Geezer Sep 20 '18 at 14:56
  • 1
    @SkepticalEmpiricist I'm afraid I can't at present. I am trying to find anything online to back up my own recollection of this. My inability to do so leaves me doubting my sanity and competence. Please keep your pinch of salt handy. – Tim Randall Sep 20 '18 at 14:59
  • @TimRandall: the *"fastbuild"* is known as [*"Unity build"*](https://stackoverflow.com/questions/543697/include-all-cpp-files-into-a-single-compilation-unit). – Jarod42 Sep 20 '18 at 15:04
  • 2
    Unity builds are an abomination. – Jonathan Wakely Sep 20 '18 at 15:22
4

Is this a good idea?

Yes, as #define has several issue, as for example:

#define SIX 1 + 5
#define NINE 8 + 1

constexpr int the_answer = SIX * NINE; // 42 and not 54

Should I put them into anonymous namespace?

If used at file scope, yes, it makes sense.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 3
    `6*9 == 42` in base 13. – Peter Sep 20 '18 at 14:18
  • _"If used at file scope, yes, it makes sense."_ Why? Your `the_answer` already has internal linkage, so isn't accessible outside the translation unit. What advantage does an anonymous namespace have? – Jonathan Wakely Sep 20 '18 at 15:22
  • @JonathanWakely: OP talked about `const` and not only `constexpr`. but indeed not required. I tend to put all file scope stuff (variables/functions/classes) in unnamed namespace. – Jarod42 Sep 20 '18 at 15:27