Ошибка: `#elif без выражения` — происходит только в Windows

Я пытаюсь скомпилировать проект, используя библиотеку, которую я сделал в Windows, используя MinGW 4.8.1 x86. Проект отлично компилируется в Linux.

Common.hpp включается в первую очередь и определяет некоторые макросы в зависимости от текущей ОС. Затем включается ConsoleFmt.hpp и включает файл, зависящий от ранее определенных макросов.

Однако я получаю сообщение об ошибке - вот код и сообщение об ошибке:


Common.hpp

#if (__linux || __unix || __posix)
    #define SSVU_OS_LINUX
#elif (_WIN64 || _WIN32)
    #define SSVU_OS_WINDOWS
#else
    #define SSVU_OS_UNKNOWN
#endif

ConsoleFmt.hpp

#include "Common.hpp"

#ifdef SSVU_OS_LINUX
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplUnix.hpp"
#elif SSVU_OS_WINDOWS
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplWin.hpp"
#else
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplNull.hpp"
#endif

Ошибка:

ошибка: #elif без выражения:

#элиф SSVU_OS_WINDOWS

Мой код недействителен или в MinGW есть ошибка? Думаю, я правильно использую #elif.


person Vittorio Romeo    schedule 30.04.2014    source источник
comment
Не могли бы вы объяснить отрицательный голос?   -  person Vittorio Romeo    schedule 30.04.2014
comment
#ifdef X совпадает с #if defined(X), а не с #if X.   -  person Kerrek SB    schedule 30.04.2014


Ответы (3)


Безопасное решение, IMO, состоит в том, чтобы определить SSVU_OS_* таким образом, чтобы не имело значения, используете ли вы #if или #ifdef.

#if (__linux || __unix || __posix)
    #define SSVU_OS_LINUX 1
#elif (_WIN64 || _WIN32)
    #define SSVU_OS_WINDOWS 1
#else
    #define SSVU_OS_UNKNOWN 1
#endif

Это позволяет вашему #ifdef/#elif работать уже как есть. Для согласованности вы можете затем очистить это до

#if SSVU_OS_LINUX
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplUnix.hpp"
#elif SSVU_OS_WINDOWS
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplWin.hpp"
#else
    #include "SSVUtils/Core/ConsoleFmt/Internal/ConsoleFmtImplNull.hpp"
#endif

но это не строго необходимо.

Убедитесь, что ваши макросы работают без проверок #ifdef/defined, что позволяет использовать более простые выражения, если вы комбинируете несколько проверок (как вы уже делаете с макросами других: вы проверяете несколько, используя ||).

person Community    schedule 30.04.2014

#elif — это сокращение #else и #if, а не #else и #ifdef, поэтому ваша строка должна выглядеть так:

#elif defined(SSVU_OS_WINDOWS)

Изменить: поскольку неопределенные макросы расширяются до 0 в выражениях #if, вы также можете использовать исходный вариант и определить активный макрос со значением 1. (Как только что опубликовал и объяснил hvd.)

person M Oehm    schedule 30.04.2014
comment
Кроме того, defined не является функцией. Скобки не нужны. - person unwind; 30.04.2014
comment
... но и не болеть. Мне они нравятся, как и sizeof. ;) - person DevSolar; 30.04.2014

Чтобы объяснить, почему это работает в Linux, но не работает в Windows:

#elif (_WIN64 || _WIN32)

Если _WIN64 был определен, он заменяется, например. если бы они были определены

#define _WIN64
#define _WIN32

затем первая строка расширяется до

#elif ( || )

что вызовет ошибку. Однако, если эти токены вообще не были определены, они заменяются на 0:

#elif (0 || 0)

что нормально.

person M.M    schedule 30.04.2014