用于空指针安全访问的C/ c++宏

C/C++ Macro for null safe pointer access

本文关键字:c++ 空指针 安全 访问 用于      更新时间:2023-10-16

我想写一个C/c++宏null安全指针访问。我目前有这个,它工作得很好:

#define NULL_SAFE(p, e) if (p) p->e
NULL_SAFE(myPtr, myMethod(myArg));

但是我真正想要的是这样的东西:

NULL_SAFE(
  myPtr, myMethod(myArg),
  myOtherPtr, myOtherMethod(myOtherArg),
  yetAnotherMyPtr, plsStopMethod(grArg),
  ...
);

展开为:

  if (myPtr) myPtr->myMethod(myArg);
  if (myOtherPtr) myOtherPtr->myOtherMethod(myOtherArg);
  if (yetAnotherMyPtr) yetAnotherMyPtr->plsStopMethod(grArg);

我可以想到一大堆我可能喜欢使用的,但它们都是基于相同的概念。

这可能吗?这已经存在了吗?有什么建议吗?谢谢你的帮助!

如果NULL检查是算法的一部分,那么只需显式地键入NULL检查,而不需要任何繁琐的宏。

如果NULL检查是防御性编程的一种方式,那么正确的方法是assert(ptr);。如果断言触发了,就去修复导致它的错误。重复此操作,直到没有bug,然后从生产质量代码中删除assert。

c++ 11:

inline void null_safe()
{
}
template <typename Ptr, typename Fn, typename... Args>
void null_safe(Ptr&& ptr, Fn&& fn, Args&&... args)
{
    if (ptr)
        fn();
    // you could put "else" here                                                                                                            
    null_safe(std::forward<Args>(args)...);
}

你可以使用任何可调用对象作为第二个参数,所以:

int f2() {
    return printf("f2n");
}
int f3() {
    return printf("f3n");
}
int main()
{
    int i1 = 1;
    null_safe(
        &i1, f2
        );
    null_safe(
        NULL, f2,
        &i1, f3
        );
}

您也可以使用任何谓词作为第一个参数。

为什么这里是NULL而不是nullptr留给读者作为练习。

我能得到的最接近这是通过使用c++11可变变量模板,和C99可变变量宏…如果您的平台不允许这样做,那么很抱歉,不管怎样,编写代码是非常有趣的!

#include <functional>
#include <iostream>
template<class T>
void stuff(T a)
{
    std::cout<< "stuff:" << a << std::endl;
}
template<class T>
void other_stuff(T a)
{
    std::cout<< "other_stuff:" << a << std::endl;
}
template <typename Test, typename ToCall>
void tester(Test t, ToCall tc)
{
    if(t) tc();
}
template <typename Test, typename ToCall, typename... Others>
void tester(Test t, ToCall tc, Others... args)
{
    if(t) tc();
    tester(args...);
}
#define FUN_WRAP(a,b) std::bind(a<decltype(b)>, (b) )
#define NULL_SAFE(...) tester(__VA_ARGS__)
int main()
{
    NULL_SAFE(1, FUN_WRAP(stuff, 1),
        0, FUN_WRAP(stuff, 2),
        1, FUN_WRAP(other_stuff, 3)
        );
}