#ifdef с несколькими токенами, это законно?

сегодня я столкнулся с некоторым кодом C++, который содержит предложение #ifdef следующим образом:

#ifdef DISABLE_UNTIL OTHER_CODE_IS_READY
   foo();
#endif

обратите внимание на пробел между "DISABLE_UNTIL"и " OTHER_CODE_IS_READY". По сути, в строке #ifdef указаны два токена.

мой вопрос в том, является ли это законным кодом C++? (g++ компилирует его без каких-либо ошибок, и он, по-видимому, просто игнорирует второй токен). И если это законно, должен ли второй токен иметь какой-либо эффект?

2 ответов


[C++11 16.1], [C++11 16.5] и, кстати, [C99 6.10.1/4] все говорят, что это неверно.

if-group:
# if константное-выражение new-line группаopt
# ifdef идентификатор new-line группаopt
# ifndef идентификатор new-line группаopt

только один идентификатор является законным.

собственная документация GCC согласен.

мои тесты предположим, что принимается только первый идентификатор, а второй просто отбрасывается; это может быть для облегчения реализации, но стандарт требует диагностики здесь, поэтому вы должны увидеть это при использовании -pedantic флаг в не менее.

#include <iostream>
using namespace std;

#define A
#define B

int main() {
    #ifdef A
    std::cout << "a ";
    #endif

    #ifdef B
    std::cout << "b ";
    #endif

    #ifdef C
    std::cout << "c ";
    #endif

    #ifdef B C
    std::cout << "bc ";
    #endif

    #ifdef C B
    std::cout << "cb ";
    #endif

    return 0;
}

// Output: "a b bc"
// Note: "cb" *not* output

установка GCC Coliru испускает его С или без -pedantic.


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

В зависимости от того, что вы надеетесь достичь, вы можете использовать || или && объединить их?
(конечно, если это чей-то код, я просто отклоню его как неуместный / непригодный)

#if defined(DISABLE_UNTIL) || defined(OTHER_CODE_IS_READY)
    foo();
#endif