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

时间:2016-06-30 12:50:53

标签: c++ c pointers null macros

我想为空安全指针访问编写一个C / C ++宏。我目前有这个,效果很好:

#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);

我可以想到我可能想要使用的一大堆这些,但它们都运行在与此相同的概念上。

这可能吗?这已经存在于某个地方吗?有什么建议?谢谢你的帮助!

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:3)

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)...);
}

您可以使用任何callable作为第二个参数,所以:

int f2() {
    return printf("f2\n");
}

int f3() {
    return printf("f3\n");
}

int main()
{
    int i1 = 1;

    null_safe(
        &i1, f2
        );

    null_safe(
        NULL, f2,
        &i1, f3
        );
}

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

为什么它在那里是NULL而不是nullptr留给读者的练习。

答案 2 :(得分:1)

我能得到的最接近的是使用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)
        );
}