Есть ли в GCC встроенное утверждение времени компиляции? - PullRequest
17 голосов
/ 12 июня 2009

Наша существующая реализация assert во время компиляции основана на отрицательном индексе массива и обеспечивает плохой диагностический вывод в GCC. static_assert в C ++ 0x - очень приятная функция, и диагностический вывод, который она предоставляет, намного лучше. Я знаю, что в GCC уже реализованы некоторые функции C ++ 0x. Кто-нибудь знает, если static_assert среди них, и если это так с какой версии GCC?

Ответы [ 8 ]

29 голосов
/ 12 июня 2009

Согласно этой странице , gcc имеет static_assert с 4.3.

16 голосов
/ 12 июня 2009

Если вам нужно использовать версию gcc, которая не поддерживает ее, вы можете использовать

#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT( /* assertion */ )

По сути, это повышение:

Объявить (но не определять!) 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) > }

Хитрость в том, что если условие ложно, компилятору необходимо создать экземпляр структуры

STATIC_ASSERTION_FAILURE< false >

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

8 голосов
/ 12 июня 2009

Следующий код работает должным образом с 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"
6 голосов
/ 13 мая 2010

Если у вас более старый gcc, или вы используете более старый стандарт C ++, или используете C, тогда вы можете эмулировать static_assert, как описано здесь: http://www.pixelbeat.org/programming/gcc/static_assert.html

1 голос
/ 06 сентября 2011

NSPR делает:

#define PR_STATIC_ASSERT(condition) \
    extern void pr_static_assert(int arg[(condition) ? 1 : -1])

, которая завершается ошибкой, если condition ложно, поскольку объявляет массив отрицательной длины.

1 голос
/ 02 апреля 2011

вы всегда можете поиграться с шаблонами и несуществующими strutures через шаблон-специализацию. Это как повысить делает это, насколько я знаю. Это то, что я использую в качестве 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
}
1 голос
/ 12 июня 2009

Это на самом деле не отвечает на вопрос, но мне больше нравятся утверждения времени компиляции, основанные на switch-case, например,

#define COMPILE_TIME_ASSERT(cond) do { switch(0) { case 0: case cond: ; } } while (0)

Работает также в C и не только в C ++.

0 голосов
/ 17 апреля 2013

Оба

    BOOST_STATIC_ASSERT(x)
    BOOST_STATIC_ASSERT_MSG(x, msg)

будет использовать C ++ 11 static_assert, если ваш компилятор поддерживает его

...