mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Improve constructor resolution in variant_caster
Currently, `py::int_(1).cast<variant<double, int>>()` fills the `double` slot of the variant. This commit switches the loader to a 2-pass scheme in order to correctly fill the `int` slot.
This commit is contained in:
parent
93e3eac6f9
commit
94d0a9f7bc
@ -315,6 +315,12 @@ struct variant_caster<V<Ts...>> {
|
||||
bool load_alternative(handle, bool, type_list<>) { return false; }
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
// Do a first pass without conversions to improve constructor resolution.
|
||||
// E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
|
||||
// slot of the variant. Without two-pass loading `double` would be filled
|
||||
// because it appears first and a conversion is possible.
|
||||
if (convert && load_alternative(src, false, type_list<Ts...>{}))
|
||||
return true;
|
||||
return load_alternative(src, convert, type_list<Ts...>{});
|
||||
}
|
||||
|
||||
|
@ -366,6 +366,10 @@ test_initializer python_types([](py::module &m) {
|
||||
return std::visit(visitor(), v);
|
||||
});
|
||||
|
||||
m.def("load_variant_2pass", [](std::variant<double, int> v) {
|
||||
return std::visit(visitor(), v);
|
||||
});
|
||||
|
||||
m.def("cast_variant", []() {
|
||||
using V = std::variant<int, std::string>;
|
||||
return py::make_tuple(V(5), V("Hello"));
|
||||
|
@ -373,12 +373,16 @@ def test_exp_optional():
|
||||
|
||||
@pytest.mark.skipif(not hasattr(pybind11_tests, "load_variant"), reason='no <variant>')
|
||||
def test_variant(doc):
|
||||
from pybind11_tests import load_variant, cast_variant
|
||||
from pybind11_tests import load_variant, load_variant_2pass, cast_variant
|
||||
|
||||
assert load_variant(1) == "int"
|
||||
assert load_variant("1") == "std::string"
|
||||
assert load_variant(1.0) == "double"
|
||||
assert load_variant(None) == "std::nullptr_t"
|
||||
|
||||
assert load_variant_2pass(1) == "int"
|
||||
assert load_variant_2pass(1.0) == "double"
|
||||
|
||||
assert cast_variant() == (5, "Hello")
|
||||
|
||||
assert doc(load_variant) == "load_variant(arg0: Union[int, str, float, None]) -> str"
|
||||
|
Loading…
Reference in New Issue
Block a user