模板元函数生成pybind11绑定

Bil*_*tor 5 c++ templates template-meta-programming pybind11

我正在尝试使用pybind11为某些C ++函数创建python绑定。这些函数是模板化的,但是在python绑定中,我需要其中一个template参数作为函数参数。目前,我对每个模板参数都有很多重复的方法。

enum MyEnum {E1, E2, E3};

template<typename T, MyEnum E>
returnType templFunction(int arg){
    <function body>
}

PYBIND11_MODULE(moduleName, m){
    m.def("pyFunction1", [](int arg, MyEnum e){
            switch(e){
                case MyEnum::E1: return templFunction<templParam1, E1>(arg);
                case MyEnum::E2: return templFunction<templParam1, E2>(arg);
                case MyEnum::E3: return templFunction<templParam1, E3>(arg);
                default: throw std::invalid_argument("Unknown enum type ...");
                }
        });

    m.def("pyFunction2", [](int arg, MyEnum e){
            switch(e){
                case MyEnum::E1: return templFunction<templParam2, E1>(arg);
                case MyEnum::E2: return templFunction<templParam2, E2>(arg);
                case MyEnum::E3: return templFunction<templParam2, E3>(arg);
                default: throw std::invalid_argument("Unknown enum type ...");
                }
        });

    // for template type temlParam3, only E1 and E2 are valid enums
    m.def("pyFunction3", [](int arg, MyEnum e){
            switch(e){
                case MyEnum::E1: return templFunction<templParam3, E1>(arg);
                case MyEnum::E2: return templFunction<templParam3, E2>(arg);
                default: throw std::invalid_argument("Unknown enum type ...");
                }
        });

    // more specializations like above

    };
Run Code Online (Sandbox Code Playgroud)

有没有一种好的方法可以使一个高阶函数,所以我不需要太多的重复代码?

我还具有其他具有相似签名和模板参数的功能。因此,理想情况下,我想将函数句柄(或函数名称)和模板参数之一传递给“元函数”,该函数可以基于枚举和给定的模板参数来生成特殊化信息。

注:我有一个静态的属性,在每个模板类型(templParam1templateParam2,...),它决定允许enum类型为模板参数。例如templParam1::allowedEnumTypes = std::vector<myEnum> { E1, E2, E3 };

Pas*_* By 1

你可以写

template<typename T, MyEnum... Cases>
return_type switcher(int arg, MyEnum e)
{
    return_type r;
    bool tests[] = {(e == Cases ? (r = templFunction<T, Cases>(arg), true) : false)...};
    for(auto t : tests)
        if(t)
            return r;
    throw std::invalid_argument("Unknown enum type ..."); 
}
Run Code Online (Sandbox Code Playgroud)

并用作

m.def("pyFunction1", switcher<templParam1, E1, E2, E3>);
m.def("pyFunction2", switcher<templParam2, E1, E2, E3>);
m.def("pyFunction3", switcher<templParam3, E1, E2>);
Run Code Online (Sandbox Code Playgroud)