Где разместить постоянные во время компиляции - PullRequest
8 голосов
/ 18 февраля 2011

Скажем, у меня есть массив, хранящий первые 10 простых чисел, например:

const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};

Это все очень хорошо и просто, если у меня есть 1 .cpp файл.Однако, если у меня есть несколько файлов .cpp, я не знаю, куда поместить этот массив.

Очевидное решение будет следующим:

// primes.h:
extern const int primes[10];

// primes.cpp:
extern const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};

Однако проблема в этомчто массив простых чисел больше не является постоянной времени компиляции.Скажем, x.cpp хочет выполнить некоторые тяжелые вычисления с использованием простых чисел [k], с константой времени компиляции ka нужно будет выполнить фактический поиск памяти.Мне это не нравится.

Итак, куда мне поместить этот массив так:

  1. Это только один раз в двоичном файле (не один раз для файла .cpp)
  2. массив [SOME_CONSTANT] также является константой времени компиляции

Edit

как насчет этого?

inline int prime(int i) {
    static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    return primes[i];
}

PS: Даже приведенное выше "очевидное решение" заняло у меня довольно много времени, чтобы написать.Очевидно, переменные const имеют внутреннюю связь по умолчанию, поэтому мне пришлось добавить extern в файл primes.cpp, чтобы он работал.

Ответы [ 3 ]

5 голосов
/ 19 февраля 2011

Я думаю, что это должно работать (теперь обновлено после того, как тестирование Migi выявило ошибку):

template <bool dummy>
struct primes_lut
{
    static const int values[];
};

template<bool dummy>
const int primes_lut<dummy>::values[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };

static auto& primes = primes_lut<true>::values;

(В C ++ нет проблемы, которая не может быть решена использованием большего количества шаблонов.)

Другой подход:

struct primes_lut { int values[10]; };
inline const primes_lut& primes_lut_provider(void)
{
    static const primes_lut values = { {2, 3, 5, 7, 11, 13, 17, 19, 23, 29} };
    return values;
}
static const int (&primes)[10] = primes_lut_provider().values;

Наконец, ни один из этих приемов не требуется для современного компоновщика, чем реализация постоянного свертывания.

1 голос
/ 18 февраля 2011

Вы можете использовать enum внутри заголовка. Перечисления гарантированно являются константами времени компиляции и (если вы не используете класс перечисления C ++ 0X) неявно преобразуются в целые числа.

0 голосов
/ 09 июля 2016
static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};

в заголовочном файле. Это может привести к увеличению размера исполняемого файла (каждый исходный файл будет иметь свою собственную копию массива), но я думаю, что та же проблема относится и к принятому в настоящее время ответу.

...