C++ Best practices for constants

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++.

C Programming Tutorial for Beginners, Learn C the Hard Way: Practical Exercises on the Computational Subjects You Keep Avoiding (Like C) The digraph ck is often used to represent the sound / k / after short vowels, like "wicket". C is the eleventh least frequently used letter in the English language (after G, Y, P, B, V, K, J, X, Q, and Z ), with a frequency of about 2.20% in words.

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.

"C" Programming Language: Brian Kernighan, This course will give you a full introduction into all of the core concepts in the C programming Duration: 3:46:13 Posted: Aug 15, 2018 Stock analysis for Citigroup Inc (C:New York) including stock price, stock chart, company news, key statistics, fundamentals and company profile.

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;

Learn C, "C" is one of the most widely used programming languages of all time. Prof Brian Kernighan Duration: 8:26 Posted: Aug 18, 2015 C-- ( pronounced cee minus minus) is a C -like programming language. Its creators, functional programming researchers Simon Peyton Jones and Norman Ramsey, designed it to be generated mainly by compilers for very high-level languages rather than written by human programmers.

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?

C Tutorial, learn-c.org is a free interactive C tutorial for people who want to learn C, fast. This is a list of operators in the C and C++ programming languages.All the operators listed exist in C++; the fourth column "Included in C", states whether an operator is also present in C. Note that C does not support operator overloading.

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.

C Language - Overview, C programming is a general-purpose, procedural, imperative computer programming language developed in 1972 by Dennis M. As well as C and Simula's influences, other languages also influenced this new language, including ALGOL 68, Ada, CLU and ML . Initially, Stroustrup's "C with Classes" added features to the C compiler, Cpre, including classes, derived classes, strong typing, inlining and default arguments.

Learn C Programming, C Language - Overview - C is a general-purpose, high-level language that was originally developed by Dennis M. Ritchie to develop the UNIX operating system​  Microsoft C++, C, and Assembler documentation. Learn how to use C++, C, and assembly language to develop applications, services, and tools for your platforms and devices.

Cprogramming.com: Learn C and C++ Programming, C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on. C++ is a middle-level programming language developed by Bjarne Stroustrup starting in 1979 at Bell Labs.C++ runs on a variety of platforms, such as Windows, Mac OS, and the various versions of UNIX. This C++ tutorial adopts a simple and practical approach to describe the concepts of C++ for beginners to advanded software engineers.. Why to Learn C++. C++ is a MUST for students and working

What is C?, The best site for C and C++ programming. Popular, beginner-friendly C and C++ tutorials to help you become an expert! C# (pronounced see sharp, like the musical note C♯, but written with the number sign) is a general-purpose, multi-paradigm programming language encompassing strong typing, lexically scoped, imperative, declarative, functional, generic, object-oriented (class-based), and component-oriented programming disciplines. It was developed around 2000 by Microsoft as part of its .NET initiative and

Comments
  • Firstly: OH NOES, A FEW KILOBYTES!! Secondly: The compiler almost certainly will fold them into one constant, even if it doesn't remove from the final executable altogether.
  • Why do you assume there is a physical copy? Unless there is a need for a physical location (like taking the address of the variable) then the compiler can quite happily optimize that away.
  • THe compiler needs to know the value of each constant during compile time, if you want to get them folded
  • Can you imagine being a Microsoft programmer and having to spend the day recompiling because something changed in Windows.h?
  • Link-time optimization will handily take care of this.
  • An extern const variable of an integral type is no longer a compile-time expression, though, and so it can no longer be used for array bounds, in case statements etc.
  • +1 When adding/changing a constant leads to almost all other source files needing to be recompiled, I call that phenomenon "recompiling the world". Someone else has probably already invented that expression.
  • They will not be constant expressions if this is done, which is problematic.
  • I'd say that it is the Java-ish approach.
  • I would say they C++ way is to wrap them in a namespace not a class.
  • @DeadMG: I would have thought that because they are const POD these are still still const expressions.
  • @LuchianGrigore Try declaring an array using an extern const variable as a bound.
  • In this situation (because they are const) I would actually use static (by that I mean I would not declare them anything just not make them extern (thus default to static)). As it provides a better opportunity for a compiler to completely optimize away the value.
  • const at global and namespace-scope level implies internal linkage, i.e. static const is the same as const, but not extern const. This behaviour was specifically implemented in C++ to avoid using macros for constants. The compiler won't put that constant into .data section of the object file if the address of that constant is not taken. It's value is going to be hardcoded, as it is essentially a compile time constant.