简体   繁体   中英

How to define compile-time (static) constant inside a C++ class?

I have some constants that only need to be used at compile-time to simplify code, so I don't need the actual variables available at runtime.

Traditionally the way this was done was with #define NAME 123 but I would like a type-safe alternative.

Outside of classes you can const int name = 123; which works fine, but it doesn't seem possible to put this inside a class. For example this:

class Example {
    public:
        const double usPerSec = 1000000.0;
};
double usOneMinute = 60 * Tempo::usPerSec;

Works with Visual C++, but doesn't work with GCC:

error: non-static const member ‘const double Example::usPerSec’,
  can’t use default assignment operator

You can fix it by making it static, but then Visual C++ complains:

error C2864: 'Example::usPerSec' : a static data member with an in-class
  initializer must have non-volatile const integral type
    type is 'const double'

I'm guessing this means VC++ will only accept static const int .

I want to avoid setting the value in the constructor because then I need an instance of the class at runtime in order to access the value, whereas really I want it all handled at compile time like it is with #define .

So how can I define a constant as a double inside a class, without resorting to making it global or using #define , that will work without having an instance of the class, and that will function with major C++03 compilers?

There is a difference here between integral and other types. For integral types you can always define them as const static members as in

struct Example
{
    const static int name = 123;  // added 'static' to code in text of question
    const static unsigned usPerSec = 1000000;
};

For non-integral types, such as double in your example, the situation is more complicated. Since 2011 (using compiler option std=c++11 with most compilers), you can simply do this:

struct Example
{
    constexpr static double usPerSec = 1000000.0;
};

But with gcc, this

struct Example
{
    const static double usPerSec = 1000000.0;
};

should work also in C++03 (it's a GNU extension).

However, the standard approach in C++03, which is also used by the standard library itself (for example in std::numeric_limits<> ), is a static member function

struct Example
{
    static double usPerSec() { return 1000000.0; }
};

I see two possible approaches with C++03:

  1. Use a static member function and rely on inlining:

     class Example { public: static double usPerSec() { return 1000000.0; } }; double usOneMinute = 60 * Example::usPerSec(); 
  2. Use a static data member and resign on constant folding (the value using the constant will be computed at runtime):

     class Example { public: static const double usPerSec; }; double usOneMinute = 60 * Example::usPerSec; // Somewhere in one .cpp const double Example::usPerSec = 1000000.0; 

If I were you I would put it in a namespace:

namespace MyExampleNamespace {
    const double usPerSec = 1000000.0;
}
double usOneMinute = 60 * MyExampleNamespace::usPerSec;

This code works on both vc++ and gcc :

class Example {
public:
    static const double usPerSec ;
};
const double Example::usPerSec=10000.0;
double usOneMinute = 60 * Example::usPerSec;

You have to make it static const and then give it value outside class. Don't do it inside constructor. You don't have to make make instance

class Example {
public:
    static const double usPerSec;

};

double Example::usPerSec = 1000000.0;

Now you can use it anywhere without making any instance of class

double someVar = Example::usPerSec;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM