Определите, передаются ли одинаковые указатели макросу

Существует множество макросов для отладки, регистрации, отображения стека и т. Д. Один из них:

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

Это более упрощенная версия макросов, которые я написал. У меня есть диалоговое окно с настраиваемым утверждением, если утверждение (время выполнения) не удается, регистрирует такую ​​ошибку проверки нуля в файл журнала. Макросы также написаны так, что не указатели проверяются во время компиляции (static-assert).

Теперь я ищу статические утверждения, чтобы проверить, действительно ли два указателя совпадают. Пример:

int* ptr;
ASSERT_IF_NULL_2(ptr, ptr);

Должен вызвать ошибку компилятора, так как оба аргумента макроса одинаковы. Мне все равно, если указатели указывают на одну и ту же память (так как эта штука — время выполнения).

Я пробовал выражение как:

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

Ни один из них не дает ошибку компиляции деления на ноль.
Кроме того, я пробовал с шаблоном, который принимает void* это аргумент шаблона:

template<void* T>
class Sample{};

Но это не позволяет указателям на локальные переменные передаваться в аргумент нетипизированного шаблона.

я использую VC9, который не поддерживает constexpr ключевое слово (даже VS2012 нет). Я попытался использовать ‘const’ вместо этого, который не выдает ошибку. Я также использовал выражение как размер массива, который всегда приводит к ошибке.

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

3

Решение

Итак, вы хотите проверить, передается ли одинаковое имя обоим аргументам, верно? Тогда этот простой трюк работает

#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
}

РЕДАКТИРОВАТЬ (ОП, Аджай):

В компиляторе Visual C ++ мы можем использовать ключевое слово для MS __if_exists дать ошибку через static-assert :

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

поскольку static_assert Ключевое слово не существует для компиляторов до VS2010, можно использовать пользовательский STATIC_ASSERT.

3

Другие решения

Хорошо, решение оказывается простым. использование static_assert а также Стрингизатор (#):

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

Демо-версия:

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!
}

что приводит к очень полезно сообщение об ошибке:

main.cpp: в функции ‘int main ()’:
main.cpp: 18: 5: ошибка: статическое утверждение не выполнено: глобальные и глобальные переменные передаются в ASSERT_TWO.
main.cpp: 19: 5: ошибка: статическое утверждение не выполнено: локальные и локальные переменные передаются в ASSERT_TWO.

Онлайн демо.

Надеюсь, это поможет.

Напоминаю, что это вам не поможет, так как вы используете VC9, но я держу этот ответ, так как он может помочь другим. На данный момент вы можете использовать другое решение, которое генерирует ошибку объявления, которая является менее полезным сообщением об ошибке по сравнению с static_assert сообщение.

5

Вы пытаетесь проверить, указывают ли указатели на одну и ту же память или они указывают на одно и то же значение?

В первом случае

xx = 1 / (ptr-ptr);

должно сработать.

во втором случае

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

должно сработать.

0

Попробуйте один из них, может быть:

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

Как указано Nawaz, вы хотите ошибку компиляции, поэтому попробуйте это:

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
-2
По вопросам рекламы [email protected]