V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amaranthf
V2EX  ›  程序员

问个比较复杂的 C++的问题,有关模板的

  •  
  •   amaranthf ·
    regomne · 2015-07-29 12:07:07 +08:00 · 3358 次点击
    这是一个创建于 3396 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在有这样一个需求,我需要一种和脚本交互的接口函数,以前是手写的:
    void MyInterface(Info info)
    {
    auto iso = info.getIsolate();
    int a = iso.getArgsInt(1);
    float b = iso.getArgsFloat(2);
    string c = iso.getArgsString(3);

    auto r = RealFunc(a,b,c);

    iso.setReturnValue(r);
    }
    这个函数会被注册到脚本引擎中,通过上述abc三行的方法获取脚本中传入的参数,然后调用C++函数RealFunc来进行处理,最后设置返回值。

    现在希望通过模板来做到这一点,最好能做到这样:

    只要调用
    InterfaceGenerator<int, float, string>(RealFunc)
    便可以返回给我一个函数,函数的内容就是上面写的MyInterface那样。具体模板参数和实际参数可以变化,但是需要返回给我那个函数。
    可以使用C++11/14等标准……
    13 条回复    2015-07-30 13:02:21 +08:00
    soli
        1
    soli  
       2015-07-29 12:48:43 +08:00   ❤️ 1
    随便一写,你随便一看。

    对不对的不知道哈。

    ```cpp

    template<class R, class F, class S, class T>
    void InterfaceGenerator( R (*RealFunc)(F, S, T) ) {
    F f;
    S s;
    T t;
    R r;

    auto iso = info.getIsolate();
    iso.getArgs(1, f);
    iso.getArgs(2, s);
    iso.getArgs(3, t);

    r = RealFunc(f, s, t);

    iso.setReturnValue(r);
    }

    class ISO {

    void getArgs(int idx, int &i);
    void getArgs(int idx, float &f);
    void getArgs(int idx, string &s);

    //...
    };

    bool RealFunc(int i, float f, string &s) {
    //...
    return true;
    }

    InterfaceGenerator<bool, int, float, string>(RealFunc);

    ```
    soli
        2
    soli  
       2015-07-29 12:49:30 +08:00
    呃,看了评论仍然没有支持 Markdown 。。。

    @Livid 老大,啥时候评论支持 Markdown 哈?
    hitmanx
        3
    hitmanx  
       2015-07-29 16:23:08 +08:00
    @soli 貌似InterfaceGenerator漏了输入参数Info。如果把这个参数加上的话,貌似Info和ISO也得弄成模板类才行。
    soli
        4
    soli  
       2015-07-29 16:27:51 +08:00
    @hitmanx 对对,漏了 info 。

    ```cpp

    template<class R, class F, class S, class T>
    void InterfaceGenerator(Info info, R (*RealFunc)(F, S, T) ) {

    ```

    这样应该差不多了。

    Info 和 ISO 不需要弄成模板类吧。
    hitmanx
        5
    hitmanx  
       2015-07-29 17:13:49 +08:00   ❤️ 1
    @soli 实际应该有不止一种ISO类(如果只有一个ISO类,那么折腾这么多就没意思啦),也会有多种它的holder Info类。而void InterfaceGenerator(Info info, R (*RealFunc)(F, S, T) )中的第一个参数在这里已经限定了是唯一指定的类型,不用模板的话,可能需要把Info弄成基类,把Info::getIsolate()弄成接口函数才行。

    不过话说我感觉这种情况如果只是这样的话,是不是用个简单的宏就行了,类似
    #define InterfaceGenerator(info, func) \
    do { \
    auto iso = info.getIsolate(); \
    iso.ret_ = func(iso.arg1_, iso.arg2_, iso.arg3_); \
    } while(0)
    knightzorro
        6
    knightzorro  
       2015-07-29 17:42:50 +08:00
    参考tuple的实现吧。
    amaranthf
        7
    amaranthf  
    OP
       2015-07-29 18:59:08 +08:00
    @soli @hitmanx 非常感谢两位的回复。
    但是很抱歉,是我的问题没说清楚……下午上班前看了下还没人回复,然后到现在才看到……

    首先我所使用的这个引擎,在注册接口的时候,只接受指定形式的接口:

    void CallbackFunc(const v8::FunctionCallbackInfo<v8::Value>& info);

    所以我需要InterfaceGenerator返回这样一个函数,形如:

    template <typename FuncType, typename Head, typename... Tail>
    auto InterfaceGenerator(FuncType func)
    {
    return [func](const v8::FunctionCallbackInfo<v8::Value>& info) // lambda表达式
    {
    // 要返回的真正的函数体
    };
    }
    然后我就可以这样进行注册:
    bool myFunc(int, char*);
    global->Set(“myFunc”, FunctionTemplate::New(isolate, InterfaceGenerator<int, char*>(myFunc)));
    这里InterfaceGenerator的功能是利用模板参数和目标函数,返回一个新的函数,其实叫wrapper更合适……

    其次转换每种参数的步骤是不一样的,不是单纯调用一个getArgs(int idx, float& f)就可以完成的,当然这一步我自己差不多知道怎么搞,写一个专用的使用模板的转换函数即可。

    最后也是我最想实现的一点,就是变参模板……就像上面代码里面那样:
    <typename Head, typename... Tail>
    但是这一步也是问题最大的,用递归的话我实在想不出来怎么把参数依次传递到最终调用的地方。其他方式好像也拆不开参数列表……
    xylophone21
        8
    xylophone21  
       2015-07-29 21:15:30 +08:00
    你需要一个代码生成器。如果参数只是简单类型(不包括指针,回调,类等)的话,用python撸一个不难。
    xylophone21
        9
    xylophone21  
       2015-07-29 21:24:00 +08:00
    顺便做个广告,给你一个参考。简单撸的为Android Binder生成C++胶水代码的Python脚本。

    https://github.com/xylophone21/android-binder-standalone

    在sidl目录,脚本写的比较乱,轻喷。
    amaranthf
        10
    amaranthf  
    OP
       2015-07-29 22:57:09 +08:00
    @xylophone21 谢谢~代码生成器我以前也写过,用来生成一些重复性代码或者数据之类的东西。但是我觉得我的这个需求应该是可以通过模板来完成的……就是设计不出来……
    yangff
        11
    yangff  
       2015-07-30 05:09:32 +08:00   ❤️ 1
    yangff
        12
    yangff  
       2015-07-30 05:11:03 +08:00
    顺便,模板还可以再优化一些,可以用模式匹配直接从func的类型中搞出agument list之类的。。
    amaranthf
        13
    amaranthf  
    OP
       2015-07-30 13:02:21 +08:00
    @yangff 谢谢,我学习一下……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2598 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:58 · PVG 23:58 · LAX 07:58 · JFK 10:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.