Лучший код для компиляции статического const int = X в VS2008 и GCC - PullRequest
6 голосов
/ 01 сентября 2011

Я столкнулся с проблемой при написании кода C ++, который должен компилироваться в Visual Studio 2008 и в GCC 4.6 (и должен также компилироваться обратно в GCC 3.4): static const int члены класса.

Прочие вопросы имеют охватываемых правил, необходимых для статических членов класса const int.В частности, стандарт и GCC требуют, чтобы переменная имела определение в одном и только одном объектном файле.

Однако Visual Studio создает ошибку LNK2005 при компиляции кода (в режиме отладки), который включает определение вфайл .cpp.

Некоторые методы, которые я пытаюсь выбрать между:

  • Инициализируйте его значением в файле .cpp, а не в заголовке.
  • Используйте препроцессор, чтобы удалить определение для MSVC.
  • Замените его перечислением.
  • Замените его макросом.

Последние два варианта не являютсяпривлекательным, и я, вероятно, не буду использовать ни один.Первый вариант прост - но мне нравится со значением в заголовке.

То, что я ищу в ответах, - это красивый, лучший метод для структурирования кода, чтобыосчастливить и GCC, и MSVC одновременно.Я надеюсь на что-то удивительно красивое, о чем я еще не думал.

Ответы [ 4 ]

3 голосов
/ 01 сентября 2011

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

class Whatever {
    enum { // ANONYMOUS!!!
        value = 42;
    };
    ...
}

Если вы не можете пойти по этому пути, #ifdef уберите определение в .cpp для MSVC, потому что если выесли определить значение в объявлении, оно всегда получит хранилище;компилятор не знает значение, поэтому он не может встроить его (ну, «генерация временного кода ссылки» должна быть способна исправить это, если он включен) и не может использовать его там, где необходима константа, такая как аргументы шаблона значения илиразмеры массивов.

2 голосов
/ 01 сентября 2011

Если вам не нравится идея использования нестандартных хаков, для VC ++ всегда есть __declspec(selectany).Насколько я понимаю, это гарантирует, что во время соединения любые конфликты будут разрешены путем исключения всех определений, кроме одного.Вы можете поместить это в блок #ifdef _MSC_VER.

1 голос
/ 01 сентября 2011

Visual C ++ 2010 принимает это:

// test.hpp:
struct test {
    static const int value;
};

// test.cpp:
#include "test.hpp"
const int test::value = 10;
0 голосов
/ 27 февраля 2014

Это все еще проблема с VS2013.Я решил эту проблему, поместив свое стандартное определение в файл cpp внутри #if, предотвращающего VS.

ах:

class A
{
public:
  static unsigned const a = 10;
};

a.cpp:

#ifndef _MSC_VER
unsigned const A::a;
#endif

Я также прокомментировал это хорошо, так что следующий парень в файле знает, какой компилятор виноват.

...