3

有一组宏,用于调试、日志记录、堆栈跟踪显示等。其中一个是:

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

这是我编写的宏的简化版本。如果断言(运行时)失败,我有自定义断言对话框,将此类空检查失败记录到日志文件中。还编写了宏,以便在编译时检查非指针(静态断言)。

现在,我正在寻找一些静态断言来检查两个指针​​是否实际上相同。例子:

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
4

4 回答 4

5

好吧,解决方案很简单。使用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:错误:静态断言失败:'global'和'global'是传递给ASSERT_TWO的相同变量。
main.cpp:19:5:错误:静态断言失败:“本地”和“本地”是传递给 ASSERT_TWO 的相同变量。

在线演示

希望有帮助。

我记得这对您没有帮助,因为您正在使用VC9,但我保留此答案,因为它可能对其他人有所帮助。截至目前,您可以使用其他生成重新声明错误的解决方案,与消息相比,该错误消息的帮助较小static_assert

于 2013-02-28T08:11:19.190 回答
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
}

编辑(由 OP,Ajay):

在 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_assertVS2010 之前的编译器不存在关键字,因此可以使用自定义编写的 STATIC_ASSERT。

于 2013-02-28T09:32:57.597 回答
0

您是否要检查指针是否指向相同的内存或它们是否指向相同的值?

在第一种情况下

xx = 1 / (ptr-ptr);

应该管用。

在第二种情况下

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

应该管用。

于 2013-02-28T08:07:03.713 回答
-2

尝试其中一种:

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
于 2013-02-28T08:00:22.680 回答