@@ -829,30 +829,38 @@ struct is_copy_constructible : std::is_copy_constructible<T> {};
829829
830830// True if Container has a dependent type mapped_type that is equivalent
831831// to Container itself
832- // Actual implementation in the SFINAE specializations below
832+ // Actual implementation in the SFINAE specialization below
833833template <typename Container, typename MappedType = Container>
834- struct sfinae_is_container_with_self_referential_mapped_type : std::false_type {};
834+ struct is_container_with_recursive_mapped_type : std::false_type {};
835835
836- // Tie-breaking between the mapped_type and the value_type specializations is trivial:
837- // The specializations are only valid if both conditions are fulfilled:
838- // 1) The mapped_type (respectively value_type) exists
836+ // This specialization is only valid if both conditions are fulfilled:
837+ // 1) The mapped_type exists
839838// 2) And it is equivalent to Container
840- // So, in each case, only one specialization will activate.
841839template <typename Container>
842- struct sfinae_is_container_with_self_referential_mapped_type <Container,
843- typename Container::mapped_type>
840+ struct is_container_with_recursive_mapped_type <Container, typename Container::mapped_type>
844841 : std::true_type {};
845842
843+ // True if Container has a dependent type value_type that is equivalent
844+ // to Container itself
845+ // Actual implementation in the SFINAE specialization below
846+ template <typename Container, typename MappedType = Container>
847+ struct is_container_with_recursive_value_type : std::false_type {};
848+
849+ // This specialization is only valid if both conditions are fulfilled:
850+ // 1) The value_type exists
851+ // 2) And it is equivalent to Container
846852template <typename Container>
847- struct sfinae_is_container_with_self_referential_mapped_type <Container,
848- typename Container::value_type>
853+ struct is_container_with_recursive_value_type <Container, typename Container::value_type>
849854 : std::true_type {};
850855
851- // Use a helper struct in order to give this a nicer public API without helper template parameter.
852- // This makes this struct nicer to specialize by users.
853- template <typename Container>
854- struct is_container_with_self_referential_mapped_type
855- : sfinae_is_container_with_self_referential_mapped_type<Container> {};
856+ // True constant if the type contains itself recursively.
857+ // By default, this will check the mapped_type and value_type dependent types.
858+ // In more complex recursion patterns, users can specialize this struct.
859+ // The second template parameter SFINAE=void is for use of std::enable_if in specializations.
860+ // An example is found in tests/test_stl_binders.cpp.
861+ template <typename Container, typename SFINAE = void >
862+ struct is_recursive_container : any_of<is_container_with_recursive_value_type<Container>,
863+ is_container_with_recursive_mapped_type<Container>> {};
856864
857865// Specialization for types that appear to be copy constructible but also look like stl containers
858866// (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if
@@ -864,7 +872,7 @@ struct is_copy_constructible<
864872 all_of<std::is_copy_constructible<Container>,
865873 std::is_same<typename Container::value_type &, typename Container::reference>,
866874 // Avoid infinite recursion
867- negation<is_container_with_self_referential_mapped_type <Container>>>::value>>
875+ negation<is_recursive_container <Container>>>::value>>
868876 : is_copy_constructible<typename Container::value_type> {};
869877
870878// Likewise for std::pair
@@ -885,7 +893,7 @@ struct is_copy_assignable<
885893 all_of<std::is_copy_assignable<Container>,
886894 std::is_same<typename Container::value_type &, typename Container::reference>,
887895 // Avoid infinite recursion
888- negation<is_container_with_self_referential_mapped_type <Container>>>::value>>
896+ negation<is_recursive_container <Container>>>::value>>
889897 : is_copy_assignable<typename Container::value_type> {};
890898template <typename T1, typename T2>
891899struct is_copy_assignable <std::pair<T1, T2>>
0 commit comments