@@ -770,10 +770,32 @@ using movable_cast_op_type =
770
770
// T is non-copyable, but code containing such a copy constructor fails to actually compile.
771
771
template <typename T, typename SFINAE = void > struct is_copy_constructible : std::is_copy_constructible<T> {};
772
772
773
+ // STL-like containers traits
774
+ template <typename T, typename _ = void > struct is_container : std::false_type {};
775
+ template <typename T> struct is_container <
776
+ T,
777
+ typename std::conditional<
778
+ false ,
779
+ void_t <
780
+ typename T::value_type,
781
+ typename T::reference,
782
+ typename T::size_type,
783
+ typename T::iterator,
784
+ typename T::const_iterator,
785
+ decltype (std::declval<T>().size()),
786
+ decltype(std::declval<T>().begin()),
787
+ decltype(std::declval<T>().end()),
788
+ decltype(std::declval<T>().cbegin()),
789
+ decltype(std::declval<T>().cend())
790
+ >,
791
+ void
792
+ >::type> : public std::true_type {};
793
+
773
794
// Specialization for types that appear to be copy constructible but also look like stl containers
774
795
// (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if
775
796
// so, copy constructability depends on whether the value_type is copy constructible.
776
797
template <typename Container> struct is_copy_constructible <Container, enable_if_t <all_of<
798
+ is_container<Container>,
777
799
std::is_copy_constructible<Container>,
778
800
std::is_same<typename Container::value_type &, typename Container::reference>
779
801
>::value>> : is_copy_constructible<typename Container::value_type> {};
0 commit comments