Skip to content

Commit a839f8f

Browse files
committed
Add recursive checks for is_move_constructible
1 parent 1bd1e7e commit a839f8f

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

include/pybind11/detail/type_caster_base.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,27 @@ struct is_recursive_container : any_of<is_container_with_recursive_value_type<Co
860860
template <typename T, typename SFINAE = void>
861861
struct is_move_constructible : std::is_move_constructible<T> {};
862862

863+
// Specialization for types that appear to be move constructible but also look like stl containers
864+
// (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if
865+
// so, move constructability depends on whether the value_type is move constructible.
866+
template <typename Container>
867+
struct is_move_constructible<
868+
Container,
869+
enable_if_t<
870+
all_of<std::is_move_constructible<Container>,
871+
std::is_same<typename Container::value_type &, typename Container::reference>,
872+
// Avoid infinite recursion
873+
negation<is_recursive_container<Container>>>::value>>
874+
: is_move_constructible<typename Container::value_type> {};
875+
876+
// Likewise for std::pair
877+
// (after C++17 it is mandatory that the move constructor not exist when the two types aren't
878+
// themselves move constructible, but this can not be relied upon when T1 or T2 are themselves
879+
// containers).
880+
template <typename T1, typename T2>
881+
struct is_move_constructible<std::pair<T1, T2>>
882+
: all_of<is_move_constructible<T1>, is_move_constructible<T2>> {};
883+
863884
// std::is_copy_constructible isn't quite enough: it lets std::vector<T> (and similar) through when
864885
// T is non-copyable, but code containing such a copy constructor fails to actually compile.
865886
template <typename T, typename SFINAE = void>

0 commit comments

Comments
 (0)