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.
`#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:
* Moved ``mkdoc.py`` to a new repo, `pybind11-mkdoc`_.
@ -164,7 +169,6 @@ Smaller or developer focused features:
.. _pre-commit: https://pre-commit.com
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
/// 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<
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>
struct is_template_base_of_impl {

View File

@ -50,6 +50,12 @@ public:
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.
/// Used to test recursive casters (e.g. std::tuple, stl containers).
struct RValueCaster {};

View File

@ -64,4 +64,10 @@ TEST_SUBMODULE(opaque_types, m) {
result->push_back("some value");
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()
assert "StringList" in repr(ptr)
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