Use Static_Assert to Check Types Passed to MACro

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");

Determine if same pointers are passed to a macro

So you want to check if same name is passed to both arguments, right? Then this simple trick works

#define ASSERT_IF_NULL_2(_ptr1, _ptr2)\
{\
int _check_##_ptr1;\
int _check_##_ptr2;\
}\
ASSERT(_ptr1);\
ASSERT(_ptr2);

int main ()
{
int* ptr1;
int* ptr2;

ASSERT_IF_NULL_2 (ptr1, ptr1); // error: redeclaration of `int _check_ptr1'
ASSERT_IF_NULL_2 (ptr1, ptr2); // OK
}

EDIT (By OP, Ajay):

On Visual C++ compiler, we can use MS specific keyword __if_exists to give error through static-assert :

 #define ASSERT_IF_NULL_2(_ptr1, _ptr2)\
{\
int _check_##_ptr1;\
__if_exists(_check_##_ptr2)
STATIC_ASSERT(false, "Same pointer passed twice")
}\

Since static_assert keyword doesnt exist for pre-VS2010 compilers, one may use custom-written STATIC_ASSERT.

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.

Static Assert to check compile-time-constant is NOT passed to macro

You could redefine the macro so that it takes the address of the parameter - that should fail for literals. However that will not prevent you from passing a constant variable, e.g.

const static int FIVE = 5;
ASSERT_FOR_DEFAULT(FIVE); // still works.

To prohibit all kinds of constants from being passed to your macro call a function that takes the parameter by non-const reference:

template <class T>  void noConstAllowed(T&){};
#define ASSERT_FOR_DEFAULT_VALUE(val) \
{ \
(void*)&(val); /* no literals*/ \
noConstAllowed(val); /* no constants at all */ \
switchHitDefaultDialog(val, __FILE__, __LINE__); \
}

I suppose you use something like FILE or other positional macros or you would have made it a function. Of yourse, you only need to use one of the two lines.

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.

Verify macro argument size at compilation time

The type of the ternary ?: expression is the common type of its second and third arguments (with integer promotion of smaller types). So the following version of your MY_MACRO will work in a 32-bit architecture:

static_assert(sizeof(uint32_t) == sizeof 0, ""); // sanity check, for your machine

#define MY_MACRO(arg0, arg1, arg2) \
do { \
static_assert(sizeof(0 ? 0 : (arg0)) == sizeof 0, ""); \
static_assert(sizeof(0 ? 0 : (arg1)) == sizeof 0, ""); \
static_assert(sizeof(0 ? 0 : (arg2)) == sizeof 0, ""); \
my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2)); \
} while (0)

Moreover, this solution should work with all versions of C and C++ (with, if necessary, a suitable definition of static_assert).

Note this macro, like the OP's original, has function semantics in that the arguments are evaluated only once, unlike for example the notorious MAX macro.



Related Topics



Leave a reply



Submit