c – 使用LambdaTemplateSFINAE自动化蹦床功能的trycatch-safeguarding

c – 使用LambdaTemplateSFINAE自动化蹦床功能的trycatch-safeguarding,第1张

概述我有100个左右的蹦床功能.我想知道是否可以在try / catch块中自动包装每个. 请提前通知,这不是一个简单的问题.我将从描述(简化)代码的问题开始,然后尝试在下面尽可能地回答它,以便读者可以看到我在哪里. Foo有一个函数指针表: 编辑:这是一个C函数指针表.所以它可以接受静态W :: w. 签名在这里:http://svn.python.org/projects/python/trunk 我有100个左右的蹦床功能.我想知道是否可以在try / catch块中自动包装每个.

请提前通知,这不是一个简单的问题.我将从描述(简化)代码的问题开始,然后尝试在下面尽可能地回答它,以便读者可以看到我在哪里.

Foo有一个函数指针表:

编辑:这是一个C函数指针表.所以它可以接受静态W :: w.
签名在这里:http://svn.python.org/projects/python/trunk/Include/object.h

编辑:我试过一个测试用例here:

class Foo {    table table;    Foo() {        // Each slot has a default lambda.        :        table->fp_53 = [](S s,A a,B b)      -> int   {cout<<"load me!";};        table->fp_54 = [](S s,C c,D d,E e) -> float {cout<<"load me!";};        // ^ Note: slots MAY have different signatures        //         only the first parameter 'S s' is guaranteed    }    // Foo also has a method for loading a particular slot:    :    voID load53() { table->fp_53 = func53; }    voID load54() { table->fp_54 = func54; }    :}

如果某个特定的插槽是“已加载”,则会将其加载到其中:

int func53(S s,B b) {     try{        return get_base(s)->f53(a,b);    }     catch(...) { return 42;} }float func54(S s,E e) {     try{        return get_base(s)->f54(c,d,e);    }     catch(...) { return 3.14;} }

我试图使用lambdas来实现这一点,以便绕过必须分别定义所有这些func53.像这样的东西:

class Foo {    :    voID load53() {         table->fp_53 =            [](S s,B b)->int { return get_base(s)->f53(a,b); }    }    voID load54() {         table->fp_54 =            [](S s,E e)->float { return get_base(s)->f54(c,e); }    }

但是,这无法捕获错误.我需要在return语句周围添加一个try / catch:

try{ return get_base(s)->f53(a,b); } catch{ return 42; }

然而,这会造成很多混乱.如果我能这样做会很好:

return trap( get_base(s)->f53(a,b); )

我的问题是:有没有办法编写这个陷阱函数(不使用#define)?

这是我到目前为止所提出的:

我认为这会传递所有必要的信息:

trap<int,&Base::f53>(s,a,b)

陷阱的定义可能如下所示:

template<typename RET,Base::Func>static RET trap(S s,...) {    try {        return get_base(s)->Func(...);    }    catch {        return std::is_integral<RET>::value ? (RET)(42) : (RET)(3.14);     }}

这可能允许非常干净的语法:

class Foo {    :    voID load53() { table->fp_53 = &trap<int,&Base::f53>; }    voID load54() { table->fp_54 = &trap<float,&Base::f54>; }}

在这一点上,我甚至不确定是否违反了某些法律. table-> fp_53必须是有效的C函数指针.

传递非静态成员函数(& Base :: f53>)的地址不会违反此规则,因为它是模板参数,并且不会影响陷阱的签名

同样,……应该没问题,因为C允许varargs.

所以,如果这确实有效,可以清理吗?

我的想法是:

1)也许……应该作为包移回模板参数.
2)也许可以推导出陷阱的返回类型,并保存一个模板参数

3)Base :: Func模板参数是非法语法.我怀疑它甚至不接近合法的东西.这可能会破坏整个方法.

解决方法
#include <utility>template <typename T,T t>struct trap;template <typename R,typename... Args,R(Base::*t)(Args...)>struct trap<R(Base::*)(Args...),t>{        static R call(int s,Args... args)    {        try        {            return (get_base(s)->*t)(std::forward<Args>(args)...);        }        catch (...)        {            return std::is_integral<R>::value ? static_cast<R>(42)                                              : static_cast<R>(3.14);         }    }};

用法:

table->fp_53 = &trap<decltype(&Base::f53),&Base::f53>::call;table->fp_54 = &trap<decltype(&Base::f54),&Base::f54>::call;

DEMO

注意:虽然Args本身不是转发引用,但仍可以使用std :: forward.

总结

以上是内存溢出为你收集整理的c – 使用Lambda / Template / SFINAE自动化蹦床功能的try / catch-safeguarding全部内容,希望文章能够帮你解决c – 使用Lambda / Template / SFINAE自动化蹦床功能的try / catch-safeguarding所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1236324.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存