Allow raw unions without base classes in is_accessible_base_of (#2320)

Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
This commit is contained in:
Boris Staletic 2020-10-02 15:39:22 +02:00 committed by GitHub
parent c72708a746
commit 5ebc78164d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 2 deletions

View File

@ -98,6 +98,11 @@ See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
``get_type_overload`` is deprecated. ``get_type_overload`` is deprecated.
`#2325 <https://github.com/pybind/pybind11/pull/2325>`_ `#2325 <https://github.com/pybind/pybind11/pull/2325>`_
* `py::class_<union_type>` is now supported. Note that writing to one data
member of the union and reading another (type punning) is UB in C++. Thus
pybind11-bound enums should never be used for such conversion.
`#2320 <https://github.com/pybind/pybind11/pull/2320>`_.
Smaller or developer focused features: Smaller or developer focused features:
* Moved ``mkdoc.py`` to a new repo, `pybind11-mkdoc`_. * Moved ``mkdoc.py`` to a new repo, `pybind11-mkdoc`_.
@ -164,7 +169,6 @@ Smaller or developer focused features:
.. _pre-commit: https://pre-commit.com .. _pre-commit: https://pre-commit.com
v2.5.0 (Mar 31, 2020) v2.5.0 (Mar 31, 2020)
----------------------------------------------------- -----------------------------------------------------

View File

@ -631,8 +631,9 @@ template <typename Base, typename Derived> using is_strict_base_of = bool_consta
/// Like is_base_of, but also requires that the base type is accessible (i.e. that a Derived pointer /// Like is_base_of, but also requires that the base type is accessible (i.e. that a Derived pointer
/// can be converted to a Base pointer) /// can be converted to a Base pointer)
/// For unions, `is_base_of<T, T>::value` is False, so we need to check `is_same` as well.
template <typename Base, typename Derived> using is_accessible_base_of = bool_constant< template <typename Base, typename Derived> using is_accessible_base_of = bool_constant<
std::is_base_of<Base, Derived>::value && std::is_convertible<Derived *, Base *>::value>; (std::is_same<Base, Derived>::value || std::is_base_of<Base, Derived>::value) && std::is_convertible<Derived *, Base *>::value>;
template <template<typename...> class Base> template <template<typename...> class Base>
struct is_template_base_of_impl { struct is_template_base_of_impl {

View File

@ -50,6 +50,12 @@ public:
IncType &operator=(IncType &&) = delete; IncType &operator=(IncType &&) = delete;
}; };
/// A simple union for basic testing
union IntFloat {
int i;
float f;
};
/// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast context. /// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast context.
/// Used to test recursive casters (e.g. std::tuple, stl containers). /// Used to test recursive casters (e.g. std::tuple, stl containers).
struct RValueCaster {}; struct RValueCaster {};

View File

@ -64,4 +64,10 @@ TEST_SUBMODULE(opaque_types, m) {
result->push_back("some value"); result->push_back("some value");
return std::unique_ptr<StringList>(result); return std::unique_ptr<StringList>(result);
}); });
// test unions
py::class_<IntFloat>(m, "IntFloat")
.def(py::init<>())
.def_readwrite("i", &IntFloat::i)
.def_readwrite("f", &IntFloat::f);
} }

View File

@ -45,3 +45,11 @@ def test_pointers(msg):
ptr = m.return_unique_ptr() ptr = m.return_unique_ptr()
assert "StringList" in repr(ptr) assert "StringList" in repr(ptr)
assert m.print_opaque_list(ptr) == "Opaque list: [some value]" assert m.print_opaque_list(ptr) == "Opaque list: [some value]"
def test_unions():
int_float_union = m.IntFloat()
int_float_union.i = 42
assert int_float_union.i == 42
int_float_union.f = 3.0
assert int_float_union.f == 3.0