Skip to content

Commit 339d70f

Browse files
committed
Add blank/monostate support
1 parent b758b05 commit 339d70f

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

include/eigenpy/variant.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ struct VariantVisitorType<ResultType, std::variant<Alternatives...> > {
4141
return std::visit(std::forward<Visitor>(visitor),
4242
std::forward<Visitable>(v));
4343
}
44+
45+
result_type operator()(std::monostate) const {
46+
return boost::python::incref(boost::python::object().ptr()); // None
47+
}
4448
};
4549

4650
template <typename... Alternatives>
@@ -61,6 +65,10 @@ struct VariantVisitorType<ResultType, boost::variant<Alternatives...> >
6165
static result_type visit(Visitor&& visitor, Visitable&& visitable) {
6266
return std::forward<Visitable>(visitable).apply_visitor(visitor);
6367
}
68+
69+
result_type operator()(boost::blank) const {
70+
return boost::python::incref(boost::python::object().ptr()); // None
71+
}
6472
};
6573

6674
template <typename... Alternatives>
@@ -84,6 +92,8 @@ struct VariantValueToObject : VariantVisitorType<PyObject*, Variant> {
8492
result_type operator()(T& t) const {
8593
return boost::python::incref(boost::python::object(t).ptr());
8694
}
95+
96+
using Base::operator();
8797
};
8898

8999
/// Convert {boost,std}::variant<class...> alternative reference to a Python
@@ -104,6 +114,9 @@ struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
104114
result_type operator()(T& t) const {
105115
return boost::python::detail::make_reference_holder::execute(&t);
106116
}
117+
118+
/// Copy the object when it's None
119+
using Base::operator();
107120
};
108121

109122
/// Converter used in \see ReturnInternalVariant.

unittest/python/test_variant.py.in

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ variant_module = importlib.import_module("@MODNAME@")
44
V1 = variant_module.V1
55
V2 = variant_module.V2
66
VariantHolder = variant_module.VariantHolder
7+
VariantNoneHolder = variant_module.VariantNoneHolder
78
make_variant = variant_module.make_variant
9+
make_variant_none = variant_module.make_variant_none
810

911
variant = make_variant()
1012
assert isinstance(variant, V1)
@@ -40,3 +42,23 @@ assert v1.v == 1000
4042
variant_holder.variant = v2
4143
assert isinstance(variant_holder.variant, V2)
4244
assert variant_holder.variant.v == v2.v
45+
46+
# Test variant that hold a None value
47+
v_none = make_variant_none()
48+
assert v_none is None
49+
v_none = 1
50+
assert v_none == 1
51+
v_none = None
52+
assert v_none is None
53+
54+
variant_none_holder = VariantNoneHolder()
55+
v_none = variant_none_holder.variant
56+
assert v_none is None
57+
58+
v1 = V1()
59+
v1.v = 1
60+
variant_none_holder.variant = v1
61+
assert variant_none_holder.variant.v == 1
62+
v1 = variant_none_holder.variant
63+
v1.v = 10
64+
assert variant_none_holder.variant.v == 10

unittest/variant.cpp.in

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,35 @@ struct V2 {
1717
};
1818
typedef VARIANT<V1, V2> MyVariant;
1919

20+
template <typename Variant>
21+
struct MyVariantNoneHelper {};
22+
23+
template <typename... Alternatives>
24+
struct MyVariantNoneHelper<boost::variant<Alternatives...> > {
25+
typedef VARIANT<boost::blank, Alternatives...> type;
26+
};
27+
28+
#ifdef EIGENPY_WITH_CXX17_SUPPORT
29+
template <typename... Alternatives>
30+
struct MyVariantNoneHelper<std::variant<Alternatives...> > {
31+
typedef VARIANT<std::monostate, Alternatives...> type;
32+
};
33+
#endif
34+
35+
typedef typename MyVariantNoneHelper<VARIANT<V1> >::type MyVariantNone;
36+
2037
MyVariant make_variant() { return V1(); }
2138

39+
MyVariantNone make_variant_none() { return MyVariantNone(); }
40+
2241
struct VariantHolder {
2342
MyVariant variant;
2443
};
2544

45+
struct VariantNoneHolder {
46+
MyVariantNone variant;
47+
};
48+
2649
BOOST_PYTHON_MODULE(@MODNAME@) {
2750
using namespace eigenpy;
2851

@@ -41,4 +64,14 @@ BOOST_PYTHON_MODULE(@MODNAME@) {
4164
bp::make_getter(&VariantHolder::variant,
4265
Converter::return_internal_reference()),
4366
bp::make_setter(&VariantHolder::variant));
67+
68+
typedef eigenpy::VariantConverter<MyVariantNone> ConverterNone;
69+
ConverterNone::registration();
70+
bp::def("make_variant_none", make_variant_none);
71+
72+
boost::python::class_<VariantNoneHolder>("VariantNoneHolder", bp::init<>())
73+
.add_property("variant",
74+
bp::make_getter(&VariantNoneHolder::variant,
75+
ConverterNone::return_internal_reference()),
76+
bp::make_setter(&VariantNoneHolder::variant));
4477
}

0 commit comments

Comments
 (0)