Pybind11:跟进用std :: initializer_list绑定函数

时间:2018-03-14 12:09:43

标签: c++11 pybind11

我知道这里有一个类似的问题:Binding a function with std::initializer_list argument using pybind11但是因为我无法发表评论(声誉不够)我在这里问我的问题:上述相关问题的结果是否也适用于构造函数:I.e。如果我有一个带std::initializer_list<T>的构造函数,那么无法绑定它吗?

1 个答案:

答案 0 :(得分:2)

至少没有简单的绑定方式。基本上,正如另一篇文章中提到的(以及我在pybind11问题跟踪器中的原始响应),我们无法动态构造std::initializer_list:它是一个编译时构造。构造函数vs方法与函数在这里无关紧要:我们无法将一组动态参数转换为编译时initializer_list结构。

但是,如果你真的陷入了需要它的C ++设计,那么让我给你一种方法,你可以部分地包装它。首先,您必须决定要支持多少个参数。例如,假设您希望在int的绑定构造函数中支持通过initializer_list<int>传递的1,2或3个MyType参数。你可以写:

#include <stl.h>

py::class_<MyType>(m, "MyClass")
    .def(py::init([](int a) { return new MyClass({ a }); }))
    .def(py::init([](int a, int b) { return new MyClass({ a, b }); }))
    .def(py::init([](int a, int b, int c) { return new MyClass({ a, b, c }); }))
    .def(py::init([](std::vector<int> v) {
        if (vals.size() == 1) return new MyClass({ v[0] });
        elsif (vals.size() == 2) return new MyClass({ v[0], v[1] });
        elsif (vals.size() == 3) return new MyClass({ v[0], v[1], v[2] });
        else throw std::runtime_error("Wrong number of ints for a MyClass");
    });

其中前三个重载将整数值作为参数,最后一个重载采用列表。 (没有理由你必须使用这两种方法 - 我只是为了举例而这样做。)

这两个都相当严重,并且不能很好地扩展,但它们表现出根本问题:initializer_list的每个大小都需要从不同的C ++中编译码。这就是为什么pybind11不能支持它:我们必须为每个可能的initializer_list参数长度编译不同版本的转换代码 - 因此,对于的任意数量的参数,二进制大小都会爆炸可能被使用,或者有一个任意的参数大小截止,超出该截止值就会开始出现致命错误。这些都不是很好的选择。

编辑:至于你的问题,具体是关于构造函数:这里没有区别。问题是我们无法将参数转换为所需类型,无论是构造函数,方法还是函数,参数转换都是相同的。