diff --git a/libcxx/include/__iterator/projected.h b/libcxx/include/__iterator/projected.h --- a/libcxx/include/__iterator/projected.h +++ b/libcxx/include/__iterator/projected.h @@ -22,17 +22,26 @@ #if !defined(_LIBCPP_HAS_NO_CONCEPTS) -template _Proj> -struct projected { - using value_type = remove_cvref_t>; - indirect_result_t<_Proj&, _It> operator*() const; // not defined +template +struct __projected_impl { + struct __type { + using value_type = remove_cvref_t>; + indirect_result_t<_Proj&, _It> operator*() const; // not defined + }; }; template -struct incrementable_traits> { - using difference_type = iter_difference_t<_It>; +struct __projected_impl<_It, _Proj> { + struct __type { + using value_type = remove_cvref_t>; + using difference_type = iter_difference_t<_It>; + indirect_result_t<_Proj&, _It> operator*() const; // not defined + }; }; +template _Proj> +using projected = typename __projected_impl<_It, _Proj>::__type; + #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_binary_predicate.compile.pass.cpp @@ -81,3 +81,9 @@ bool operator()(std::iter_common_reference_t, std::iter_common_reference_t) const = delete; }; static_assert(!std::indirect_binary_predicate); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(std::indirect_binary_predicate*>, Holder**, Holder**>); +static_assert(!std::indirect_binary_predicate*, Holder**, Holder**>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_equivalence_relation.compile.pass.cpp @@ -96,3 +96,9 @@ bool operator()(std::iter_common_reference_t, std::iter_common_reference_t) const = delete; }; static_assert(!std::indirect_equivalence_relation); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(std::indirect_equivalence_relation*>, Holder**, Holder**>); +static_assert(!std::indirect_equivalence_relation*, Holder**, Holder**>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_result_t.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_result_t.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_result_t.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_result_t.compile.pass.cpp @@ -30,3 +30,13 @@ static_assert(!has_indirect_result); // int isn't indirectly_readable static_assert(!has_indirect_result); // int isn't invocable + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(std::same_as, int>); +static_assert(std::same_as&(&)(int), int*>, Holder&>); +static_assert(std::same_as*(&)(int), int*>, Holder*>); +static_assert(std::same_as*), Holder**>, int>); +static_assert(std::same_as&(&)(Holder*), Holder**>, Holder&>); +static_assert(std::same_as*(&)(Holder*), Holder**>, Holder*>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_strict_weak_order.compile.pass.cpp @@ -96,3 +96,9 @@ bool operator()(std::iter_common_reference_t, std::iter_common_reference_t) const = delete; }; static_assert(!std::indirect_strict_weak_order); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(std::indirect_strict_weak_order*>, Holder**, Holder**>); +static_assert(!std::indirect_strict_weak_order*, Holder**, Holder**>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirect_unary_predicate.compile.pass.cpp @@ -63,3 +63,10 @@ bool operator()(std::iter_common_reference_t) const = delete; }; static_assert(!std::indirect_unary_predicate); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +struct HolderIncompletePred { bool operator()(Holder*) const; }; +static_assert(std::indirect_unary_predicate**>); +static_assert(!std::indirect_unary_predicate*, Holder**>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp @@ -49,3 +49,9 @@ static_assert(subsumes(std::less())); static_assert(is_subsumed(std::less())); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +static_assert(std::indirectly_comparable**, Holder**, std::less*>>); +static_assert(!std::indirectly_comparable**, Holder**, Holder*>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_regular_unary_invocable.compile.pass.cpp @@ -86,3 +86,10 @@ static_assert(!std::indirectly_regular_unary_invocable); static_assert(!std::indirectly_regular_unary_invocable); static_assert(!std::indirectly_regular_unary_invocable); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +struct HolderIncompletePred { bool operator()(Holder*) const; }; +static_assert(std::indirectly_regular_unary_invocable**>); +static_assert(!std::indirectly_regular_unary_invocable*, Holder**>); diff --git a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_unary_invocable.compile.pass.cpp @@ -86,3 +86,10 @@ static_assert(!std::indirectly_unary_invocable); static_assert(!std::indirectly_unary_invocable); static_assert(!std::indirectly_unary_invocable); + +// Test ADL-proofing. +struct Incomplete; +template struct Holder { T t; }; +struct HolderIncompletePred { bool operator()(Holder*) const; }; +static_assert(std::indirectly_unary_invocable**>); +static_assert(!std::indirectly_unary_invocable*, Holder**>);