Fakher Mokadem
Fakher Mokadem

Reputation: 1099

Where to define class constants in C++?

In C++, to have a tidier code, I want to declare a set of values as constants in my header file, example :

constexpr float SIZE_SMALL = 1.5f; 
constexpr float SIZE_MEDIUM = 2.5f; 
constexpr std::string COLOR_RED = "RED"; 
constexpr std::string MATERIAL_SILK = "SILK";
...etc

But this is getting too long and clumsy. Also, some constants can be grouped together because they describe different values of the same property e.g. SIZE_SMALL and SIZE_MEDIUM.

What is the best way to write this in my header file? I thought about structs e.g.

struct SIZE
{
float SMALL; 
float MEDIUM; 
}

but then I have to declare and define a variable in my .cpp and that kinda beats the purpose of all this.

Upvotes: 4

Views: 2314

Answers (2)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122820

then I have to declare and define a variable in my .cpp and that kinda beats the purpose of all this.

No you dont. You can make the fields static and constexpr :

struct SIZES {
    static constexpr const float SMALL = 1.5f;
};

However, I recommend to not do this. Not only you do not have to create an instance of this class, but also you should not create an instance of this class (what for?). So why use a class in the first place? Use namespaces instead to group constants:

namespace SIZES {
    constexpr float SMALL = 1.5f; 
}

I have some 50+ of these constants in the same name space

Unless you find a way to make the compiler read your mind, you have to write them all down somewhere. Serisously, the only way this could be condesned is if there is some relation between those constants, as eg SMALL + 1.0f = MEDIUM, but thats not apparent from your question.

Upvotes: 6

Konrad Rudolph
Konrad Rudolph

Reputation: 545865

This depends on your actual usage but consider using proper strong types instead of basic types. For instance, to declare sizes, make them of type size, not float. This doesn’t directly solve your grouping problem but it gives you all of the other benefits of strong typing, and may also help with grouping:

struct size {
private: float value;
public:
    explicit constexpr size(float value) : value{value} {}
    explicit constexpr operator float() const noexcept { return value; }
};

namespace default_sizes {
    constexpr auto SMALL = size{1.5f};
    constexpr auto MEDIUM = size{2.5f};
    // …
}

In fact, for domain-specific usage, except in very limited cases, I’d generally avoid bare basic types and always encapsulate them in their own domain-specific type.

Upvotes: 6

Related Questions