Question

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
Was it helpful?

Solution 2

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.

OTHER TIPS

Alright, the solution turns out to be simple. Use static_assert and Stringizing Operator (#):

#define ASSERT_TWO(a,b) static_assert((void*)#a != (void*) #b, "'" #a  "' and '" #b "' are same variables passed to ASSERT_TWO.") 

Demo:

int *global;    

int main()
{
    int *local;

    ASSERT_TWO(global, local);  //should pass
    ASSERT_TWO(local, global);  //should pass

    ASSERT_TWO(global, global); //should fail
    ASSERT_TWO(local, local);   //should fail

    (void)local; //suppress unsused warning!
}

which results in very helpful error message:

main.cpp: In function 'int main()':
main.cpp:18:5: error: static assertion failed: 'global' and 'global' are same variables passed to ASSERT_TWO.
main.cpp:19:5: error: static assertion failed: 'local' and 'local' are same variables passed to ASSERT_TWO.

Online demo.

Hope that helps.

I recall that this will not help you, as you're using VC9, but I keep this answer as it might help others. As of now, you could use other solution which generates redeclaration error which is less helpful error message compared to the static_assert message.

Are you trying to check if the pointers point to the same memory or if they point at the same value?

In the first case

xx = 1 / (ptr-ptr);

should work.

in the second case

xx = 1 / (*ptr-*ptr);

should work.

Try one of these maybe:

ASSERT_IF_NULL(ptr1 == ptr1);
ASSERT(ptr1 != ptr2)

As pointed outby Nawaz you want a compile error so try this:

1/(ptr1 != ptr2);
1/static_cast<int>(ptr1 != ptr2);
static_assert(ptr1 != ptr2, "Pointers are different")       //if you dont use c++0x look here:http://stackoverflow.com/a/1664651/258418
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top