How to Do Static_Assert with MACros

How to do static_assert with macros?

Prior to C++11 I would normally do:

typedef int static_assert_something[something ? 1 : -1];

You can also look at boost static assert. But it is too bloated for my liking. It is easy to make things bigger, it is hard to make them any better.

static_assert in a macro but also expand to something that can be used as a function parameter

You should be using std::extent instead of that macro, which gives you 0 for unsupported types (e.g. arrays without bounds, non-array types).

For your use case a constexpr function that gives you the size for an array variable would be better suited, like so:

template <typename T, std::size_t N>
constexpr std::size_t arrsize(T (&)[N]) {
return N;
}

Then you don't need to assert on the size since you can only use the function with actual arrays.

How to static_assert in an expression out of function bodies in C

@Tavian Barnes's comment solves my problem. My updated program looks like:

#include <stdio.h>

#define PAGE_ALIGN(x) (sizeof(struct { _Static_assert(sizeof(x) == 4); int dummy; }) * 0 + ((x) & 0xfffff000U))

char a[PAGE_ALIGN(0x12345678U)];

int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}

Static assert in C

C11 standard adds the _Static_assert keyword.

This is implemented since gcc-4.6:

_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */

The first slot needs to be an integral constant expression. The second slot is a constant string literal which can be long (_Static_assert(0, L"assertion of doom!")).

I should note that this is also implemented in recent versions of clang.

Use static_assert to check types passed to macro

I found this to be the cleanest, using @UncleBens suggestion:

#include <type_traits>

static_assert(std::is_same<decltype(retval), bool>::value, "retval must be bool");

static_assert inside a macro throwing compile time errors even when it shouldn't (Visual Studio)

@1201ProgramAlarm answered in the comments. The solution was to use std::remove_reference to remove the reference added to the ptr when it is passed into the lambda. The final macro was:

#define cast_to_A(ptr) ([&] () { \
static_assert( \
std::is_same<std::shared_ptr<Node>, std::remove_reference<decltype(ptr)>::type>::value, \
"Cannot cast to an A pointer." \
); \
return std::static_pointer_cast<A>(ptr); \
})()

Now only the expected "bad cast" throws an error

What does this one-line, macro function, 'static_assert' do?

This performs an assert by triggering a compile-time error. Consider this code:

switch(0) case 0: case 0:

The compiler will tell you that you have a duplicate case label, because zero is listed twice. If, on the other hand, you would put any number other than zero in place of x, you would get

switch(1) case 0: case 1:

which is perfectly legal, and would not trigger a compile-time error.

Unlike the regular assert which happens at run time, this assert happens at compile time. In other words, if the regular assertion is false, the program would crash; if this assertion is false, the program would not even compile.



Related Topics



Leave a reply



Submit