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
For Loop Prints an Extra Comma
"Cannot Evaluate Function -- May Be In-Lined" Error in Gdb for Stl Template Container
How Can Cstring Be Passed to Format String %S
Question About Pure Virtual Destructor
How to Check If a File Has Been Opened by Another Application in C++
Calculate A*A Mod N Without Overflow
Qt 5 and Qprocess Redirect Stdout with Signal/Slot Readyread
Std::Pow Produce Different Result in 32 Bit and 64 Bit Application
C++ When Is It Ok to Extend the 'Std' Namespace
Traceback a Pointer in C++ Code Gdb
Const Variable Changed with Pointer in C
Mixing Templates with Polymorphism
How Does a Sentinel Node Offer Benefits Over Null