使用C++11实现C++17的apply(动态数组用作函数参数)

标题有点错误,apply是用tuple做参数,调用一个函数。这个标题是为了能更好的适配搜索关键字。动态数组用作函数参数更适合嵌入了脚本环境的C++程序,比如lua或javascript(js)。

若有疏忽或改进,请评论,谢谢。

VS2017虽然实现了一些C++17特性,但没有apply(也许我没发现或有替代),而且即使以后更新添加了,也不是很满足我提到的数组转参数列表。

下面是VS2015.3测试通过的代码。

写脚本封装(Wrapper)功能一般都是把C++函数(一般是成员函数)注册到脚本的环境,我看了很多开源作者都重载了很多模板类/模板函数,其实都挺类的,虽然都是一些体力活,但一旦修改就是批量的。

本文参考了stackoverflow的Johannes Schaub的回复,附录有链接。

代码中的intint只是一个自动转换例子而已,什么也没做,你可以替换为你的脚本对象转原生对象的转换器。

代码的核心部分是嵌套的模板类继承,这一段比较烧脑子:

template<int ...>struct seq {};
template<int N, int ...S> struct gen_seq : gen_seq<N - 1, N - 1, S...> {};// 嵌套继承,为了得到一个N-M至N的参数序列,是无限的
template<int ...S> struct gen_seq<1, S...> { typedef seq<S...> type; };// 特例。对上面嵌套继承的一个终止,终止条件是1开始到N

全部代码,无输出,请自行添加,同样,也不需要其它头文件:

struct intint {
    int i;
    intint(int i) :i(i) {}
    operator int() { return i; }
};

template<int ...>struct seq {};
template<int N, int ...S> struct gen_seq : gen_seq<N - 1, N - 1, S...> {};
template<int ...S> struct gen_seq<1, S...> { typedef seq<S...> type; };

template<typename T, typename R, typename...TS>
struct callable {
    typename gen_seq<sizeof...(TS)+1>::type fo;
    R(T::*func)(TS...);
    callable(R(T::*func)(TS...)) :func(func) {}
    template<int ...S>
    void call(seq<S...>, int* v) {
        (new T->*func)(intint(v[S])...);
    }
    void operator()(T*, int* v) {
        call(fo, v);
    }
};

struct foo
{
    void func(int, int, int, int) {
    }
};

int main()
{
    callable<foo, void, int, int, int, int> c(&foo::func);
    int v[] = { 100,200,300,400,500,600 };
    c(new foo(), v);
    return 0;
}

猜你喜欢

转载自www.linuxidc.com/Linux/2017-06/145193.htm