有没有简单的方法来检查C ++中的不安全表达式? [英] Is there a simple way to check unsafe expression in C++?

查看:72
本文介绍了有没有简单的方法来检查C ++中的不安全表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种[更好]的方式来运行/检查可能不安全的表达式或以更优雅的方式执行多个空检查。

I'm trying to find a [better] way to run/check a potentially unsafe expression or perform multiple null checks in a more elegant way.

这里是我想改善的代码示例:

Here is an example of codes I would like to improve:

if (myObjectPointer &&
    myObjectPointer->getSubObject() &&
    myObjectPointer->getSubObject()->getSubSubObject() &&
    myObjectPointer->getSubObject()->getSubSubObject()->getTarget()) {

  // Use safely target
  ... *(myObjectPointer->getSubObject()->getSubSubObject()->getTarget()) ...
}

我试图找到一种更优雅的方法来实现此目的(而不是上面的详细空值检查) )。这是我的第一个想法:

I tried to find a more elegant way to achieve this (instead of the above verbose null checks). Here is my first thoughts:

template<typename T>
bool isSafe(T && function) {
   try {
       function(); 
       // Just running the func above, but we could e.g. think about returning the actual value instead of true/fase - not that important. 
       return true;
    }
    catch (...) {
       return false;
    }
}

...
// And use the above as follow :
if(isSafe([&](){ myObjectPointer->getSubObject()->getSubSubObject()->getTarget(); })) {
    // Use safely target
}
...

上述问题是我们无法捕获信号(分段错误,...)。而且我显然不想处理程序中的所有信号,而只希望处理这个非常具体的check / eval函数。

The problem with the above is that we can't catch signals (Segmentation fault, ...). And I obviously don't want to handle all signals in the program, but only in this very specific check/eval function.

我要解决错误的问题道路 ?还有其他建议吗?还是冗长的if是否不可避免?

I'm I tackling the problem the wrong way ? Any other recommendations ? or the verbose if is inevitable ?

非常感谢。

推荐答案

我正在考虑这一点,就像Jarod42所说的那样,肯定有一些可变参数模板。我不是最擅长的,但想出了这个办法:

I was thinking about this, and like Jarod42 said, there must be some variadic template stuff. I'm not the best at this, but came up with this:

#include <memory>
#include <functional>
#include <iostream>

template <typename T, typename MemFn, typename... Params> 
void safeExecute(T* ptr, MemFn memFn, Params&&... params) {
    if (ptr != nullptr)
        safeExecute(std::invoke(memFn, ptr), std::forward<Params>(params)...);
}

template <typename T, typename MemFn>
void safeExecute(T* ptr, MemFn memFn) {
    if (ptr != nullptr) std::invoke(memFn, ptr);
}


struct Target {
    void Bar() { std::cout << "tada!\n"; };
};


template<typename T>
class Object {
private:
    std::unique_ptr<T> ptr;
public:
    Object() : ptr(std::make_unique<T>()) {}

    T* Get() { return ptr.get(); }
};

using SubSubObject = Object<Target>;
using SubObject = Object<SubSubObject>;
using MyObject = Object<SubObject>;

int main() {
    auto myObjectPtr = std::make_unique<MyObject>();

    safeExecute(myObjectPtr.get(),
                &MyObject::Get,
                &SubObject::Get,
                &SubSubObject::Get,
                &Target::Bar);
}






编辑:
我一直在考虑使用更通用的返回类型,因此我尝试了不调用成员函数,而是返回指向对象的std :: optional指针的选项。这使我进入以下代码:


edit: I've been playing with the idea of having a more general return type, so I experimented with the option not to call the member function, but to return an std::optional pointer to the object. This lead me to the following code:

#include <memory>
#include <functional>
#include <iostream>
#include <optional>

template <typename T, typename MemFn, typename... Params>
auto safeGetObject(T* ptr, MemFn memFn, Params&&... params)
    -> decltype(safeGetObject(std::invoke(memFn, std::declval<T>()), std::forward<Params>(params)...))
{
    if (ptr != nullptr) return safeGetObject(std::invoke(memFn, ptr), std::forward<Params>(params)...);
    return {};
}

template <typename T, typename MemFn>
auto safeGetObject(T* ptr, MemFn memFn) -> std::optional<decltype(std::invoke(memFn, std::declval<T>()))> {
    if (ptr != nullptr) return std::invoke(memFn, ptr);
    return {};
}

struct Target {
    int Bar(int a, int b) const noexcept {
        return a+b;
    };
};

template<typename T>
class Object {
private:
    std::unique_ptr<T> ptr;
public:
    Object() noexcept : ptr(std::make_unique<T>()) {}

    T* Get() const noexcept { return ptr.get(); }
};

using SubSubObject = Object<Target>;
using SubObject = Object<SubSubObject>;
using MyObject = Object<SubObject>;

int main() {
    auto myObjectPtr = std::make_unique<MyObject>();

    auto optionalTarget = safeGetObject(
        myObjectPtr.get(),
        &MyObject::Get,
        &SubObject::Get,
        &SubSubObject::Get);

    auto result = optionalTarget ? optionalTarget.value()->Bar(3, 4) : -1;
    std::cout << " result " << result << '\n';
}

这篇关于有没有简单的方法来检查C ++中的不安全表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆