-
Notifications
You must be signed in to change notification settings - Fork 252
Open
Description
Problem description
The implementation of nb::init
uses list-initialization (i.e. curly braces) when creating an object of the bound class. Therefore the compiler always prefers a user-defined constructor with std::initializer_list
parameter (see the reproducible example).
The documentation for nb::init also says that
nb::class_<MyType>(m, "MyType")
.def(nb::init<const char*, int>());
is syntax sugar for the following lower-level implementation using “placement new”:
nb::class_<MyType>(m, "MyType")
.def("__init__",
[](MyType* t, const char* arg0, int arg1) {
new (t) MyType(arg0, arg1);
});
but this is not the case – the documentation snippet does not use list-initialization.
I think this is a bug because the expression nb::init<const char*, int>()
or even just nb::init<int>()
says nothing about list-initialization and it is not possible for the user to avoid it.
Reproducible example code
#include <initializer_list>
#include <iostream>
#include <vector>
#include <nanobind/nanobind.h>
namespace nb = nanobind;
class A
{
using T = int;
std::vector<T> data;
public:
A(std::size_t count)
: data(count)
{
std::cout << "constructor with std::size_t count\n";
}
A(std::initializer_list<T> init)
: data(init)
{
std::cout << "constructor with std::initializer_list<T> init\n";
}
};
NB_MODULE(nanobind_example_ext, m) {
nb::class_<A>(m, "A")
.def(nb::init<std::size_t>());
}
Then in Python:
>>> import nanobind_example
>>> nanobind_example.A(1)
constructor with std::initializer_list<T> init
Metadata
Metadata
Assignees
Labels
No labels