Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions stl/inc/__msvc_iter_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ _EXPORT_STD struct random_access_iterator_tag : bidirectional_iterator_tag {};
#ifdef __cpp_lib_concepts
_EXPORT_STD struct contiguous_iterator_tag : random_access_iterator_tag {};

template <class _Ty>
using _With_reference = _Ty&;

template <class _Ty>
concept _Can_reference = requires { typename _With_reference<_Ty>; };

template <class _Ty>
concept _Dereferenceable = requires(_Ty& __t) {
{ *__t } -> _Can_reference;
Expand Down
9 changes: 5 additions & 4 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ namespace ranges {
template <class _It>
concept _Has_arrow = input_iterator<_It> && (is_pointer_v<_It> || _Has_member_arrow<_It&>);

template <bool _IsConst, class _Ty>
using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>;
Comment thread
CaseyCarter marked this conversation as resolved.

template <bool _IsWrapped, class _Ty>
using _Maybe_wrapped = conditional_t<_IsWrapped, _Ty, _Unwrapped_t<_Ty>>;

Expand Down Expand Up @@ -8213,9 +8210,13 @@ namespace ranges {
private:
friend zip_view;

#ifdef __clang__ // TRANSITION, LLVM-61763
public:
#else // ^^^ workaround / no workaround vvv
template <class _Func, class... _OtherViews>
requires _Zip_transform_constraints<_Func, _OtherViews...>
friend class zip_transform_view;
#endif // ^^^ no workaround ^^^

using _My_tuple = tuple<iterator_t<_Maybe_const<_IsConst, _ViewTypes>>...>;

Expand Down Expand Up @@ -9047,7 +9048,7 @@ namespace ranges {
private:
friend adjacent_view;

#ifdef __clang__ // TRANSITION, Clang 17
#ifdef __clang__ // TRANSITION, LLVM-61763
public:
#else // ^^^ workaround / no workaround vvv
template <class _Vw2, class _Fn, size_t _Nx2>
Expand Down
3 changes: 3 additions & 0 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -2513,6 +2513,9 @@ _NODISCARD constexpr _To _Bit_cast(const _From& _Val) noexcept {
return __builtin_bit_cast(_To, _Val);
}

template <bool _IsConst, class _Ty>
using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>;

#if _HAS_TR1_NAMESPACE
_STL_DISABLE_DEPRECATED_WARNING
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
Expand Down
41 changes: 6 additions & 35 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -898,20 +898,6 @@ _NODISCARD constexpr bool in_range(const _Ty _Value) noexcept {

return true;
}

#ifdef __cpp_lib_concepts
template <class _Ty>
using _With_reference = _Ty&;

template <class _Ty>
concept _Can_reference = requires { typename _With_reference<_Ty>; };
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
template <class _Ty, class = void>
inline constexpr bool _Can_reference = false;

template <class _Ty>
inline constexpr bool _Can_reference<_Ty, void_t<_Ty&>> = true;
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
#endif // _HAS_CXX20

#if _HAS_CXX23
Expand All @@ -927,29 +913,14 @@ _EXPORT_STD [[noreturn]] __forceinline void unreachable() noexcept /* strengthen
#endif // defined(_DEBUG)
}

template <class _Ty, class _Uty,
class _Tmp = _Maybe_const<is_const_v<remove_reference_t<_Ty>>, remove_reference_t<_Uty>>>
using _Forward_like_t = conditional_t<is_rvalue_reference_v<_Ty&&>, _Tmp&&, _Tmp&>;
Comment thread
CaseyCarter marked this conversation as resolved.

_EXPORT_STD template <class _Ty, class _Uty>
_NODISCARD _MSVC_INTRINSIC constexpr auto&& forward_like(_Uty&& _Ux) noexcept {
static_assert(_Can_reference<_Ty>, "std::forward_like's first template argument must be a referenceable type.");

using _UnrefT = remove_reference_t<_Ty>;
using _UnrefU = remove_reference_t<_Uty>;
if constexpr (is_const_v<_UnrefT>) {
if constexpr (is_lvalue_reference_v<_Ty>) {
return static_cast<const _UnrefU&>(_Ux);
} else {
return static_cast<const _UnrefU&&>(_Ux);
}
} else {
if constexpr (is_lvalue_reference_v<_Ty>) {
return static_cast<_UnrefU&>(_Ux);
} else {
return static_cast<_UnrefU&&>(_Ux);
}
}
_NODISCARD _MSVC_INTRINSIC constexpr _Forward_like_t<_Ty, _Uty> forward_like(_Uty&& _Ux) noexcept {
return static_cast<_Forward_like_t<_Ty, _Uty>>(_Ux);
}

template <class _Ty, class _Uty>
using _Forward_like_t = decltype(_STD forward_like<_Ty>(_STD declval<_Uty&>()));
#endif // _HAS_CXX23

#if _HAS_TR1_NAMESPACE
Expand Down
49 changes: 26 additions & 23 deletions tests/std/tests/P2321R2_views_zip_transform/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <ranges>
#include <span>
#include <tuple>
#include <type_traits>
#include <utility>

#include <range_algorithm_support.hpp>
Expand All @@ -18,9 +19,12 @@ using namespace std;
template <class RangeType>
using AllView = views::all_t<RangeType>;

template <bool IsConst, class T>
using maybe_const = conditional_t<IsConst, const T, T>;

template <bool IsConst, class TransformType, ranges::input_range... RangeTypes>
using TransformResultType = invoke_result_t<ranges::_Maybe_const<IsConst, TransformType>&,
ranges::range_reference_t<ranges::_Maybe_const<IsConst, RangeTypes>>...>;
using TransformResultType = invoke_result_t<maybe_const<IsConst, TransformType>&,
ranges::range_reference_t<maybe_const<IsConst, RangeTypes>>...>;

template <bool IsConst, class T>
constexpr auto& maybe_as_const(T& value) {
Expand Down Expand Up @@ -50,8 +54,8 @@ constexpr bool validate_iterators_sentinels(
constexpr bool is_const = same_as<LocalZipTransformType, add_const_t<LocalZipTransformType>>;

using InnerView = ranges::zip_view<AllView<RangeTypes>...>;
using BaseType = ranges::_Maybe_const<is_const, InnerView>;
using ZipIteratorTupleType = tuple<ranges::iterator_t<ranges::_Maybe_const<is_const, AllView<RangeTypes>>>...>;
using BaseType = maybe_const<is_const, InnerView>;
using ZipIteratorTupleType = tuple<ranges::iterator_t<maybe_const<is_const, AllView<RangeTypes>>>...>;

// Validate iterator type aliases
{
Expand All @@ -66,8 +70,8 @@ constexpr bool validate_iterators_sentinels(
STATIC_ASSERT(same_as<Cat, input_iterator_tag>);
} else {
constexpr auto check_iterator_tags_closure = []<class TagType>() {
return (derived_from<typename iterator_traits<ranges::iterator_t<
ranges::_Maybe_const<is_const, RangeTypes>>>::iterator_category,
return (derived_from<typename iterator_traits<
ranges::iterator_t<maybe_const<is_const, RangeTypes>>>::iterator_category,
TagType>
&& ...);
};
Expand Down Expand Up @@ -125,10 +129,9 @@ constexpr bool validate_iterators_sentinels(
//
// Notably, parent_t is a pointer and inner_.current_ is a tuple, and operator->() on a pointer and
// std::get(std::tuple<...>) are both noexcept. We thus simplify the noexcept check as follows:
STATIC_ASSERT(
noexcept(*itr)
== noexcept(invoke(*declval<const ranges::_Movable_box<TransformType>&>(),
*declval<const ranges::iterator_t<ranges::_Maybe_const<is_const, AllView<RangeTypes>>>&>()...)));
STATIC_ASSERT(noexcept(*itr)
== noexcept(invoke(*declval<const ranges::_Movable_box<TransformType>&>(),
*declval<const ranges::iterator_t<maybe_const<is_const, AllView<RangeTypes>>>&>()...)));
}

STATIC_ASSERT(noexcept(++itr) == noexcept(++declval<ranges::iterator_t<BaseType>&>()));
Expand Down Expand Up @@ -232,7 +235,7 @@ constexpr bool validate_iterators_sentinels(
// Validate sentinel operator overloads
{
const auto validate_iterator_sentinel_equality_closure = [&]<bool IteratorConst>() {
using comparison_iterator_t = ranges::iterator_t<ranges::_Maybe_const<IteratorConst, InnerView>>;
using comparison_iterator_t = ranges::iterator_t<maybe_const<IteratorConst, InnerView>>;
using comparison_sentinel_t = ranges::sentinel_t<BaseType>;

if constexpr (sentinel_for<comparison_sentinel_t, comparison_iterator_t>) {
Expand All @@ -254,11 +257,11 @@ constexpr bool validate_iterators_sentinels(

{
const auto validate_iterator_sentinel_difference_closure = [&]<bool IteratorConst>() {
using comparison_iterator_t = ranges::iterator_t<ranges::_Maybe_const<IteratorConst, InnerView>>;
using comparison_iterator_t = ranges::iterator_t<maybe_const<IteratorConst, InnerView>>;
using comparison_sentinel_t = ranges::sentinel_t<BaseType>;

if constexpr (sized_sentinel_for<comparison_sentinel_t, comparison_iterator_t>) {
using difference_type = ranges::range_difference_t<ranges::_Maybe_const<IteratorConst, InnerView>>;
using difference_type = ranges::range_difference_t<maybe_const<IteratorConst, InnerView>>;

const auto comparison_itr = maybe_as_const<IteratorConst>(relevant_range).begin();

Expand Down Expand Up @@ -515,9 +518,9 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC
// Validate view_interface::front()
{
const auto validate_front_closure = [&]<bool IsConst>() {
STATIC_ASSERT(CanMemberFront<ranges::_Maybe_const<IsConst, ZipTransformType>>
== ranges::forward_range<ranges::_Maybe_const<IsConst, ZipTransformType>>);
if constexpr (CanMemberFront<ranges::_Maybe_const<IsConst, ZipTransformType>>) {
STATIC_ASSERT(CanMemberFront<maybe_const<IsConst, ZipTransformType>>
== ranges::forward_range<maybe_const<IsConst, ZipTransformType>>);
if constexpr (CanMemberFront<maybe_const<IsConst, ZipTransformType>>) {
using transform_result_t = TransformResultType<IsConst, TransformType, RangeTypes...>;
same_as<transform_result_t> auto first_result =
maybe_as_const<IsConst>(zipped_transformed_range).front();
Expand All @@ -533,10 +536,10 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC
// Validate view_interface::back()
{
const auto validate_back_closure = [&]<bool IsConst>() {
STATIC_ASSERT(CanMemberBack<ranges::_Maybe_const<IsConst, ZipTransformType>>
== (ranges::bidirectional_range<ranges::_Maybe_const<IsConst, ZipTransformType>>
&& ranges::common_range<ranges::_Maybe_const<IsConst, ZipTransformType>>) );
if constexpr (CanMemberBack<ranges::_Maybe_const<IsConst, ZipTransformType>>) {
STATIC_ASSERT(CanMemberBack<maybe_const<IsConst, ZipTransformType>>
== (ranges::bidirectional_range<maybe_const<IsConst, ZipTransformType>>
&& ranges::common_range<maybe_const<IsConst, ZipTransformType>>) );
if constexpr (CanMemberBack<maybe_const<IsConst, ZipTransformType>>) {
using transform_result_t = TransformResultType<IsConst, TransformType, RangeTypes...>;
same_as<transform_result_t> auto last_result =
maybe_as_const<IsConst>(zipped_transformed_range).back();
Expand All @@ -552,9 +555,9 @@ constexpr bool test_one(TransformType_&& transformer, const TransformedElementsC
// Validate view_interface::operator[]
{
const auto validate_random_access_closure = [&]<bool IsConst>() {
STATIC_ASSERT(CanIndex<ranges::_Maybe_const<IsConst, ZipTransformType>>
== ranges::random_access_range<ranges::_Maybe_const<IsConst, ZipTransformType>>);
if constexpr (CanIndex<ranges::_Maybe_const<IsConst, ZipTransformType>>) {
STATIC_ASSERT(CanIndex<maybe_const<IsConst, ZipTransformType>>
== ranges::random_access_range<maybe_const<IsConst, ZipTransformType>>);
if constexpr (CanIndex<maybe_const<IsConst, ZipTransformType>>) {
using transform_result_t = TransformResultType<IsConst, TransformType, RangeTypes...>;
same_as<transform_result_t> auto first_result =
maybe_as_const<IsConst>(zipped_transformed_range)[0];
Expand Down