Как определить постоянную времени компиляции (статическую) внутри класса C ++?

У меня есть некоторые константы, которые нужно использовать только во время компиляции для упрощения кода, поэтому мне не нужны фактические переменные, доступные во время выполнения.

Традиционно способ, которым это было сделано, был с #define NAME 123 но я бы хотел безопасную альтернативу.

Вне занятий вы можете const int name = 123; который работает нормально, но не представляется возможным поместить это в класс. Например это:

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

Работает с Visual C ++, но не работает с GCC:

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

Вы можете исправить это, сделав его статичным, но тогда Visual C ++ жалуется:

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

Я предполагаю, что это означает, что VC ++ будет принимать только static const int,

Я хочу избежать установки значения в конструкторе, потому что тогда мне нужен экземпляр класса во время выполнения для доступа к значению, тогда как на самом деле я хочу, чтобы все это обрабатывалось во время компиляции, как это происходит с #define,

Итак, как я могу определить константу как double внутри класса, не прибегая к тому, чтобы сделать его глобальным или использовать #define, это будет работать без экземпляра класса, и это будет работать с основными компиляторами C ++ 03?

5

Решение

Здесь есть разница между интегральным и другими типами. Для целочисленных типов вы всегда можете определить их как const static участники как в

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

Для нецелых типов, таких как double в вашем примере ситуация сложнее. С 2011 года (с использованием опции компилятора std=c++11 с большинством компиляторов), вы можете просто сделать это:

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

Но с GCC это

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

должен работать также в C ++ 03 (это расширение GNU).

Тем не менее, стандартный подход в C ++ 03, который также используется самой стандартной библиотекой (например, в std::numeric_limits<>), это static функция-член

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

Другие решения

Я вижу два возможных подхода с C ++ 03:

  1. Используйте статическую функцию-член и положитесь на встраивание:

    class Example {
    public:
    static double usPerSec() { return 1000000.0; }
    };
    double usOneMinute = 60 * Example::usPerSec();
    
  2. Используйте статический член данных и подайте в отставку при сворачивании констант (значение, использующее константу, будет вычислено во время выполнения):

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

На вашем месте я бы поместил это в пространство имен:

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

Этот код работает как на vc ++, так и на gcc:

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

Вы должны сделать его статическим const, а затем присвоить ему значение вне класса. Не делай этого внутри конструктора. Вам не нужно делать экземпляр

class Example {
public:
static const double usPerSec;

};

double Example::usPerSec = 1000000.0;

Теперь вы можете использовать его где угодно без создания экземпляра класса

double someVar = Example::usPerSec;
1