Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
Problem description
Hello,
I am evaluating pybind11 and I was able to wrap many things without trouble, until trying to wrap a function taking a std::variant as argument. In the documentation I understand that I do not need to use type_caster
because it it seems to me that it is already defined in pybind11/stl.h
for std::variant. However I think I am missing something, because I would expect to have to call some py::class_
function specifically for the variant (?).
I found no example for wrapping a std::variant in the documentation or elsewhere on the internet or in pybind's test suite. Sorry if this is actually trivial.
Here is an example code and associated compilation error I have with MSVC:
pybind11\include\pybind11/pybind11.h(167): error C2280: 'pybind11::detail::argument_loader<pybind11::detail::value_and_holder &,MyVariant>::argument_loader(void)': attempting to reference a deleted function
pybind11\include\pybind11\cast.h(1445): note: compiler has generated 'pybind11::detail::argument_loader<pybind11::detail::value_and_holder &,MyVariant>::argument_loader' here
pybind11\include\pybind11\cast.h(1445): note: 'pybind11::detail::argument_loader<pybind11::detail::value_and_holder &,MyVariant>::argument_loader(void)': function was implicitly deleted because a data member 'pybind11::detail::argument_loader<pybind11::detail::value_and_holder &,MyVariant>::argcasters' has either no appropriate default constructor or overload resolution was ambiguous
pybind11\include\pybind11\cast.h(1444): note: see declaration of 'pybind11::detail::argument_loader<pybind11::detail::value_and_holder &,MyVariant>::argcasters'
ybind11\include\pybind11/pybind11.h(99): note: see reference to function template instantiation 'void pybind11::cpp_function::initialize<Ty,R,pybind11::detail::value_and_holder&,MyVariant,pybind11::name,pybind11::is_method,pybind11::sibling,pybind11::detail::is_new_style_constructor>(Func &&,Return (cdecl *)(pybind11::detail::value_and_holder &,MyVariant),const pybind11::name &,const pybind11::is_method &,const pybind11::sibling &,const pybind11::detail::is_new_style_constructor &)' being compiled
with
[
Ty=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>,
R=void,
Func=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>,
Return=void
]
pybind11\include\pybind11/pybind11.h(1557): note: see reference to function template instantiation 'pybind11::cpp_function::cpp_function<Ty,pybind11::name,pybind11::is_method,pybind11::sibling,pybind11::detail::is_new_style_constructor,void>(Func &&,const pybind11::name &,const pybind11::is_method &,const pybind11::sibling &,const pybind11::detail::is_new_style_constructor &)' being compiled
with
[
Ty=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>,
Func=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>
]
pybind11\include\pybind11\detail/init.h(199): note: see reference to function template instantiation 'pybind11::class &pybind11::class::def<pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>,pybind11::detail::is_new_style_constructor>(const char *,Func &&,const pybind11::detail::is_new_style_constructor &)' being compiled
with
[
Func=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>
]
pybind11\include\pybind11\detail/init.h(200): note: see reference to function template instantiation 'pybind11::class &pybind11::class::def<pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>,pybind11::detail::is_new_style_constructor>(const char *,Func &&,const pybind11::detail::is_new_style_constructor &)' being compiled
with
[
Func=pybind11::detail::initimpl::constructor::execute::<lambda_4bce0e84265d89e846bdadb006aa47c7>
]
pybind11\include\pybind11/pybind11.h(1594): note: see reference to function template instantiation 'void pybind11::detail::initimpl::constructor::execute<pybind11::class,,0>(Class &)' being compiled
with
[
Class=pybind11::class
]
pybind11\include\pybind11/pybind11.h(1596): note: see reference to function template instantiation 'void pybind11::detail::initimpl::constructor::execute<pybind11::class_,,0>(Class &)' being compiled
with
[
Class=pybind11::class_
]
pybind_example.cpp(27): note: see reference to function template instantiation 'pybind11::class_ &pybind11::class_::def<MyVariant,>(const pybind11::detail::initimpl::constructor &)' being compiled
pybind_example.cpp(28): note: see reference to function template instantiation 'pybind11::class_ &pybind11::class_::def<MyVariant,>(const pybind11::detail::initimpl::constructor &)' being compiled
Reproducible example code
#include <variant>
#include <vector>
class MyClassA
{
public:
MyClassA(double x) {}
};
class MyClassB
{
public:
MyClassB(const std::vector<double>& x) {}
};
using MyVariant = std::variant<MyClassA, MyClassB>;
class MyTestClass
{
public:
MyTestClass(const MyVariant& variant) {}
};
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
PYBIND11_MODULE(MyModule, m) {
py::class_<MyClassA>(m, "MyClassA")
.def(py::init<double>());
py::class_<MyClassB>(m, "MyClassB")
.def(py::init<std::vector<double>>());
py::class_<MyTestClass>(m, "MyTestClass")
.def(py::init<MyVariant>()); // compilation problem here
}
Example code which does not reproduce
#include <variant>
class MyClassA
{
public:
MyClassA() {}
};
class MyClassB
{
public:
MyClassB(double x) {}
};
using MyVariant = std::variant<MyClassA, MyClassB>;
class MyTestClass
{
public:
MyTestClass(const MyVariant& variant) {}
};
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
PYBIND11_MODULE(MyModule, m) {
py::class_<MyClassA>(m, "MyClassA")
.def(py::init<>());
py::class_<MyClassB>(m, "MyClassB")
.def(py::init<double>());
py::class_<MyTestClass>(m, "MyTestClass")
.def(py::init<MyVariant>()); // compilation problem here
}