20

Our existing compile-time assert implementation is based on negative array index, and it provides poor diagnostic output on GCC. C++0x's static_assert is a very nice feature, and the diagnostic output it provides is much better. I know GCC has already implemented some C++0x features. Does anyone know if static_assert is among them and if it is then since what GCC version?

Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
VladLosev
  • 7,296
  • 2
  • 35
  • 46
  • 2
    http://en.wikichip.org/wiki/c/static_assertions – Jonathon Reinhart Jun 02 '15 at 23:21
  • 2
    So as to not have my same answer on two questions, let me post this link instead: Here's a simple macro in an answer I just wrote that utilizes gcc's `_Static_assert()` in C and C++11's `static_assert` so that it works with `gcc`, `gcc -std=c90`, `gcc -std=c99`, `gcc -std=c11`, and `g++ -std=c++11`, etc: https://stackoverflow.com/a/54993033/4561887 – Gabriel Staples Mar 04 '19 at 23:26

8 Answers8

30

According to this page, gcc has had static_assert since 4.3.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
18

If you need to use a GCC version which does not support static_assert you can use:

#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT( /* assertion */ )

Basically, what boost does is this:

Declare (but don't define!) a

template< bool Condition > struct STATIC_ASSERTION_FAILURE;

Define a specialization for the case that the assertion holds:

template <> struct STATIC_ASSERTION_FAILURE< true > {};

Then you can define STATIC_ASSERT like this:

#define STATIC_ASSERT(Condition) \ 
  enum { dummy = sizeof(STATIC_ASSERTION_FAILURE< (bool)(Condition) > ) }

The trick is that if Condition is false the compiler needs to instantiate the struct

STATIC_ASSERTION_FAILURE< false >

in order to compute its size, and this fails since it is not defined.

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Tobias
  • 6,388
  • 4
  • 39
  • 64
  • 2
    I wonder if there's any way to make a sensible error message appear from a trick like this... – Thomas May 13 '10 at 10:34
  • According to the documentation (http://www.boost.org/doc/libs/1_43_0/doc/html/boost_staticassert.html), this is one of the goals of Boost.StaticAssert: “One of the aims of BOOST_STATIC_ASSERT is to generate readable error messages. These immediately tell the user that a library is being used in a manner that is not supported.” – Philipp May 13 '10 at 11:23
  • There's a missing parenthesis in `...(Condition) > }`, should probably be `...(Condition) > ) }`. I tried to edit this but was rejected... – mbschenkel Apr 10 '15 at 20:46
9

The following code works as expected with g++ 4.4.0 when compiled with the -std=c++0x flag:

int main() {
    static_assert( false, "that was false" );
}

it displays:

x.cpp: In function 'int main()':
x.cpp:2: error: static assertion failed: "that was false"
  • 1
    For C in gcc, replace `static_assert` with `_Static_assert` for this to work. I just tested it using C online here: https://www.onlinegdb.com/. Using `static_assert` failed to work. – Gabriel Staples Mar 04 '19 at 19:42
6

If you have an older gcc or use an older C++ standard, or use C, then you can emulate static_assert as described here: http://www.pixelbeat.org/programming/gcc/static_assert.html

pixelbeat
  • 30,615
  • 9
  • 51
  • 60
2

NSPR does:

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

which fails if condition is false because it declares an array of negative length.

Justin L.
  • 3,957
  • 3
  • 31
  • 29
2

This doesn't really answer the question, but I like compile-time asserts based on switch-case better, e.g.

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

Works also in C and not only in C++.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • 4
    This technique has two shortcomings. First, such assertion can not be used at class or namespace level. And second, when assertion is successfull, it generates executable code, inflating the binary. It is left to your optimizing compiler to remove it, and that is not guaranteed. :-( – VladLosev Jun 12 '09 at 23:10
1

you can always play around with templates and non-existant strutures via template-specialization. This is how boost does it as far as I know. This is what I use as a static_assert, it's pretty straight forward.

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__  ()
}

Example Of Use

int main(int argc, char **argv)
{
    static_assert(sizeof(int) == 1)           // Error
    static_assert(sizeof(int) == sizeof(int)) // OK
}
graphitemaster
  • 3,483
  • 4
  • 19
  • 14
0

Both

    BOOST_STATIC_ASSERT(x)
    BOOST_STATIC_ASSERT_MSG(x, msg)

will use the C++11 static_assert if your compiler supports it