c++ - 异常安全蹦床的设计模式

标签 c++ c++11 trampolines

这个问题来自 here .然而,之前的问题措辞太糟糕(实际上是错误的),建议我从头开始再问。

我有一张 C 函数指针表。

一些 C 代码(让我们称之为 lib-X)有一个基本的构建 block (让我们称之为 X 对象)。每个 X 对象都可以调用此表上的函数。

这些表函数通常具有不同的签名(参见 typedefs here ),尽管多个函数可以共享相同的签名。表中大约有 100 个这样的函数。

在 C++ 中,每个 X 对象都有一个关联的 Final:Base 类。

我想将这些调用转发给 X 对象的相应 C++ Final 实例,但我想将其包含在 try/catch 中,因为 C++ 使用者可能会提供有问题的 Final。

所以我有一个 C++ 基类,它对表中的每个条目都有一个虚函数。

然后我有一个派生自基类的 C++ Final 类(可能有很多;Final1 Final2 Final3 等)。

所以现在我只需要编写一个处理程序

  1. 获取第一个“self”参数(它始终是指向调用该函数的 X 对象的指针)

  2. 检索关联的 C++ 基类实例。

  3. 在 try catch block 中,调用相应的虚函数,转发所有剩余参数,

  4. ... 这将在 Final 中实际调用覆盖。

这有点像试图理解盗梦空间的情节。 lib-X 实际上是 Python 运行时,尽管我试图保持通用性。

问题是有许多这样的函数,这会导致一些非常困惑且难以维护的 C++ 代码——如果我必须为每个函数手动编写一个 trampoline 函数,如下所示:

extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw )
{
    try
    {
        PythonExtensionBase *p = getPythonExtensionBase( self );
        if( kw != NULL )
            return new_reference_to( p->call( Object(args), :Object(kw) ) );
        else
            return new_reference_to( p->call( Object(args), Object() ) );
    }
    catch( Py::Exception & )
    {
        return NULL; // indicate error
    }
}

(来源 here)

我正试图想出一个紧凑的设计来允许这种异常安全的蹦床。

我目前的进度是[已删除,请参阅下面的答案]

最佳答案

是这样的吗?

template<typename RET, class ...Args> // <-- one trap for each f in Base that gets enabled!
RET trap( RET (Base::*f)(Args...), void* self, Args&&...args )
{
    try {
        auto base = reinterpret_cast<Base*>(self);
        return (base->*f)(std::forward<Args>(args)...);
    }
    catch (...) {
        return (RET)0;
    }
}

关于c++ - 异常安全蹦床的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27826117/

相关文章:

c++ - 如何关闭使用 SHCreateStreamOnFile 打开的文件句柄

c++ - C++ 元编程中的蹦床

scala - Applicative vs. monadic 组合器和 Scalaz 中的自由 monad

javascript - 如何将 TaskT 与 Trampoline 的 monad 实例结合起来进行无堆栈异步计算?

c++ - 写入全局变量的顺序

c++ - Cuda blockDim.y 总是==1

c++ - c++ 中的 vector 这么慢吗?

c++ - Stroustrup 在定义变量时使用 auto 的原因

c++ - C++ Actor 系统的消息接收

c++ - 有一个空捕获列表的 lambda 不能默认构造的原因吗?