Есть ли замена static_assert, которая удовлетворяет стандарту C99?

Я пытаюсь реализовать метод, аналогичный static_assert, который определен в стандарте С++ 11. Основная проблема заключается в том, как компилятор С++ записывает текстовое сообщение, передаваемое в static_assert, как const char*? Я могу заставить компилятор написать сообщение типа A_is_not_POD. Это то, что у меня есть:

#define MY_STATIC_ASSERT(condition, name)         \
   typedef char name[(condition) ? 1 : -1]; 

Но было бы неплохо заставить компилятор написать что-то вроде "Error: A is not POD." Любые предложения?

Ответ 1

Не уверен, что я понимаю вопрос, но у C11 есть _Static_assert(condition, errmessage). В C99 эта функция отсутствовала, но, в зависимости от компилятора, можно было эмулировать. Например. для gcc (unfortulately clang не поддерживает атрибут (ошибка))

#define MY_STATIC_ASSERT(cnd, descr) ({ \
    extern int __attribute__ ((error("static assert failed: (" #cnd ") (" #descr ")"))) \
               compile_time_check(void); \
    ((cnd) ? 0 : compile_time_check()), 0; \
})

Ответ 2

В стандарте c99 нет никакого "официального" способа выполнения статического утверждения в вашем компиляторе С++.

"Основная проблема заключается в том, как компилятор С++ записывает текстовое сообщение, передаваемое static_assert в виде const char *?"

Компилятор С++ обнаруживает ошибку в коде и выводит соответствующее сообщение об ошибке на основе стандартного списка сообщений, которые он имеет для каждой ошибки, которая, как известно, может возникнуть. В c99 компилятор не знает, что такое static assert error ", поэтому вам нужно вызвать некоторую другую ошибку.

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

В вашем примере

#define MY_STATIC_ASSERT(condition, name)         \
    typedef char name[(condition) ? 1 : -1];
MY_STATIC_ASSERT(false, my_error_msg)

будет вызывать сообщение "error: size of array ‘my_error_msg’ is negative" в компиляторе gcc (и, если вы хотите, похожее сообщение в других компиляторах!). Предоставление массива сообщение об ошибке для name было способом распечатать вашу собственную информацию. Существуют различные другие методы/хаки, которые вы можете сделать специально, например, плохие шаблоны, enums ссылка

Примечание. вы можете предоставить настраиваемые сообщения компилятора до С++ 11 с использованием макросов pre-processor, таких как #error или #pragma. Однако время предварительной обработки не совпадает с компиляцией! Препроцессор имеет ограниченную способность оценивать многие выражения и ключевые слова, такие как "if", "sizeof", "return" и т.д., Не имеют смысла для препроцессора, только компилятор. ссылка с некоторым обзором