Search code examples
c++templatesvisual-c++compiler-errorsstatic-assert

Determine if same pointers are passed to a macro


There are set of macros, for debugging, logging, stack-trace displaying etc. One of them is like:

#define ASSERT_IF_NULL_2(_ptr1, _ptr2) \ 
    ASSERT(_ptr1);  \
    ASSERT(_ptr2);

This is over simplified version of macro(s) I have written. I have custom-assertion dialog box if assertion (runtime) fails, logs such null-check failure into log file. Macros are also written such that non-pointers are checked at compile time (static-assert).

Now, I am looking for some static-assert to check if two pointers are actually same. Example:

int* ptr;
ASSERT_IF_NULL_2(ptr, ptr);

Should raise a compiler error since both arguments to macro are same. I don't care if pointers point to same memory (since that thing is runtime).

I have tried expression like:

int xx;
xx = 1 / (ptr-ptr);
xx = 1 / (&ptr - &ptr);

None of them gives divide-by-zero compiler error. Also, I have tried with template that takes void* is template argument:

template<void* T>
class Sample{};

But it doesn't allow local-variable pointers to be passed to template non-type argument.

I am using VC9, which doesn't support constexpr keyword (even VS2012 doesn't). I tried using 'const' instead, which doesnt throw error. I also used the expression as array-size, which always results in error.

int array[(&ptr - &ptr)]; // Even with ptrdiff_t

Solution

  • 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.