Есть ли замена 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"
и т.д., Не имеют смысла для препроцессора, только компилятор. ссылка с некоторым обзором