Skip to content

Commit 0bcc6f7

Browse files
Speculatively implement LWG-4270
1 parent 7841cf8 commit 0bcc6f7

File tree

3 files changed

+28
-24
lines changed

3 files changed

+28
-24
lines changed

stl/inc/xutility

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -866,8 +866,33 @@ namespace ranges {
866866
template <class _Ty>
867867
concept _Can_deref = requires(_Ty&& __t) { *static_cast<_Ty&&>(__t); };
868868

869+
struct _Must_have_ADL_found_iter_move_or_be_dereferenceable {};
870+
869871
class _Cpo {
870872
private:
873+
template <class _Ty>
874+
_NODISCARD static auto _Choose_return_type() {
875+
if constexpr (_Has_ADL<_Ty>) {
876+
return type_identity<decltype(iter_move(_STD declval<_Ty>()))>{}; // intentional ADL
877+
} else if constexpr (_Can_deref<_Ty>) {
878+
using _Ref = decltype(*_STD declval<_Ty>());
879+
if constexpr (is_function_v<remove_reference_t<_Ref>>) {
880+
// TRANSITION, VSO-1008447, VSO-2066340
881+
// Fuse this into the type_identity<_Ref>{} branch once MSVC is fixed.
882+
return type_identity<_Ref&>{};
883+
} else if constexpr (is_lvalue_reference_v<_Ref>) {
884+
return type_identity<remove_reference_t<_Ref>&&>{};
885+
} else {
886+
return type_identity<_Ref>{};
887+
}
888+
} else {
889+
return _Must_have_ADL_found_iter_move_or_be_dereferenceable{};
890+
}
891+
}
892+
893+
template <class _Ty>
894+
using _Return_type = decltype(_Choose_return_type<_Ty>())::type;
895+
871896
enum class _St { _None, _Custom, _Fallback };
872897

873898
template <class _Ty>
@@ -886,8 +911,7 @@ namespace ranges {
886911

887912
public:
888913
template <class _Ty>
889-
requires (_Choice<_Ty>._Strategy != _St::_None)
890-
_NODISCARD _STATIC_CALL_OPERATOR constexpr decltype(auto) operator()(_Ty&& _Val) _CONST_CALL_OPERATOR
914+
_NODISCARD _STATIC_CALL_OPERATOR constexpr _Return_type<_Ty> operator()(_Ty&& _Val) _CONST_CALL_OPERATOR
891915
noexcept(_Choice<_Ty>._No_throw) {
892916
constexpr _St _Strat = _Choice<_Ty>._Strategy;
893917

@@ -1121,7 +1145,8 @@ struct _Projected_impl {
11211145

11221146
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
11231147
[[noreturn]] indirect_result_t<_Proj&, _It> operator*() const {
1124-
_CSTD abort(); // shouldn't be called, see GH-3888
1148+
static_assert(
1149+
false, "std::projected::operator*() can't be instantiated (N5008 [projected] as modified by LWG-4270)");
11251150
}
11261151
};
11271152
};

tests/libcxx/expected_results.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,12 +1172,6 @@ std/containers/sequences/vector.bool/vector_bool.pass.cpp FAIL
11721172
# Not analyzed. Inspecting shift operators for quoted().
11731173
std/input.output/iostream.format/quoted.manip/quoted_traits.compile.pass.cpp FAIL
11741174

1175-
# Not analyzed.
1176-
# MSVC warning C5046: 'test_undefined_internal::A::operator *': Symbol involving type with internal linkage not defined
1177-
# Clang error: function 'test_undefined_internal()::A::operator*' has internal linkage but is not defined [-Werror,-Wundefined-internal]
1178-
std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_rvalue_reference_t.compile.pass.cpp FAIL
1179-
std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.comp/op_spaceship.pass.cpp FAIL
1180-
11811175
# Not analyzed. Failing assert(arr[0].moves() == 1 && arr[1].moves() == 3).
11821176
std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp FAIL
11831177

@@ -1526,9 +1520,6 @@ std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_
15261520
# Clang assertion: std::hermite(n, +inf) == inf
15271521
std/numerics/c.math/hermite.pass.cpp FAIL
15281522

1529-
# Not analyzed. Test coverage for LLVM-104496 uses span<Incomplete>.
1530-
std/containers/views/views.span/span.cons/copy.pass.cpp FAIL
1531-
15321523
# Not analyzed. These tests disable or limit allocations, which interferes with our proxy objects.
15331524
std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp FAIL
15341525
std/containers/sequences/vector/vector.capacity/shrink_to_fit_exceptions.pass.cpp FAIL

tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,15 +1073,7 @@ namespace iterator_cust_move_test {
10731073
static_assert(noexcept(ranges::iter_move(static_cast<int const*>(&some_ints[2]))));
10741074

10751075
static_assert(same_as<iter_rvalue_reference_t<int[]>, int&&>);
1076-
#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1008447
10771076
static_assert(same_as<iter_rvalue_reference_t<int(int)>, int (&)(int)>);
1078-
#else // ^^^ no workaround / workaround vvv
1079-
#ifdef _MSVC_INTERNAL_TESTING // TRANSITION, assertion will fire once VSO-2066340 ships.
1080-
static_assert(same_as<iter_rvalue_reference_t<int(int)>, int (&&)(int)>);
1081-
#else // ^^^ defined(_MSVC_INTERNAL_TESTING) / !defined(_MSVC_INTERNAL_TESTING) vvv
1082-
static_assert(same_as<iter_rvalue_reference_t<int(int)>, int (*)(int)>);
1083-
#endif // ^^^ !defined(_MSVC_INTERNAL_TESTING)
1084-
#endif // ^^^ workaround ^^^
10851077

10861078
static_assert(same_as<iter_rvalue_reference_t<int[4]>, int&&>);
10871079
static_assert(ranges::iter_move(some_ints) == 0);
@@ -1090,11 +1082,7 @@ namespace iterator_cust_move_test {
10901082
constexpr int f(int i) noexcept {
10911083
return i + 1;
10921084
}
1093-
#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1008447
10941085
static_assert(same_as<iter_rvalue_reference_t<int (*)(int)>, int (&)(int)>);
1095-
#else // ^^^ no workaround / workaround vvv
1096-
static_assert(same_as<iter_rvalue_reference_t<int (*)(int)>, int (&&)(int)>);
1097-
#endif // ^^^ workaround ^^^
10981086
static_assert(ranges::iter_move(&f)(42) == 43);
10991087
static_assert(noexcept(ranges::iter_move(&f)));
11001088

0 commit comments

Comments
 (0)