Ответ 1
Согласно эта страница, gcc имеет static_assert
с 4.3.
Наша существующая реализация утверждения времени компиляции основана на отрицательном индексе массива, и он обеспечивает плохой диагностический вывод в GCC. С++ 0x static_assert
- очень приятная функция, а предоставляемый ею диагностический вывод намного лучше. Я знаю, что GCC уже реализовал некоторые функции С++ 0x. Кто-нибудь знает, есть ли static_assert
среди них, и если это так, то какая версия GCC?
Согласно эта страница, gcc имеет static_assert
с 4.3.
Если вам нужна версия gcc, которая не поддерживает ее, вы можете использовать
#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT( /* assertion */ )
В основном, что такое boost:
Объявить (но не определять!) a
template< bool Condition > struct STATIC_ASSERTION_FAILURE;
Определить специализацию для случая, когда выполняется утверждение:
template <> struct STATIC_ASSERTION_FAILURE< true > {};
Затем вы можете определить STATIC_ASSERT следующим образом:
#define STATIC_ASSERT(Condition) \
enum { dummy = sizeof(STATIC_ASSERTION_FAILURE< (bool)(Condition) > }
Фокус в том, что если условие false, компилятор должен создать экземпляр структуры
STATIC_ASSERTION_FAILURE< false >
чтобы вычислить его размер, и это не удается, поскольку оно не определено.
Следующий код работает, как и ожидалось, с g++ 4.4.0 при компиляции с флагом -std=c++0x
:
int main() {
static_assert( false, "that was false" );
}
он отображает:
x.cpp: In function 'int main()':
x.cpp:2: error: static assertion failed: "that was false"
Если у вас есть более старый gcc или используйте более старый стандарт С++ или используйте C, вы можете эмулировать static_assert, как описано здесь: http://www.pixelbeat.org/programming/gcc/static_assert.html
Это на самом деле не отвечает на вопрос, но мне больше нравятся утверждения времени компиляции на основе кода коммутатора, например.
#define COMPILE_TIME_ASSERT(cond) do { switch(0) { case 0: case cond: ; } } while (0)
Работает также в C и не только на С++.
вы всегда можете играть с шаблонами и несуществующими с помощью шаблона-специализации. Именно так насколько я знаю. Это то, что я использую как static_assert, это довольно прямолинейно.
namespace Internal
{
template<bool x> struct SASSERT_F;
template< > struct SASSERT_F <true> {};
template<int x> struct SASSERT_P {};
#define STATIC_ASSERT(B) \
typedef Internal::SASSERT_P <( \
sizeof (Internal::SASSERT_F <( \
((B)? true : false)) >) \
)> \
StaticAssert##__LINE__ ()
}
Пример использования
int main(int argc, char **argv)
{
static_assert(sizeof(int) == 1) // Error
static_assert(sizeof(int) == sizeof(int)) // OK
}
NSPR делает:
#define PR_STATIC_ASSERT(condition) \
extern void pr_static_assert(int arg[(condition) ? 1 : -1])
который терпит неудачу, если condition
является ложным, потому что он объявляет массив отрицательной длины.
И
BOOST_STATIC_ASSERT(x)
BOOST_STATIC_ASSERT_MSG(x, msg)
будет использовать С++ 11 static_assert, если ваш компилятор поддерживает его