Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ranges iota #39

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c4a3ccf
[libc++] Implement ranges::iota and ranges::out_value_result
jamesETsmith Sep 28, 2023
1b808ec
Merge branch 'main' of https://github.com/llvm/llvm-project into rang…
jamesETsmith Sep 28, 2023
574c94c
[libc++] Implement ranges::iota: update module and docs info
jamesETsmith Sep 29, 2023
e4cfe00
[libc++] Implement ranges::iota: fixing formatting issues for out_val…
jamesETsmith Sep 29, 2023
7cdfea2
[libc++] Implement ranges::iota: Cleaning up tests for ranges::iota a…
jamesETsmith Oct 7, 2023
a1d015c
[libc++] Implement ranges::iota: Cleaning up tests for ranges::iota a…
jamesETsmith Oct 7, 2023
ab4c67d
[libc++] Implement ranges::iota: Using clang-format-17 to make CI che…
jamesETsmith Oct 7, 2023
c44d7d6
Merge branch 'main' of https://github.com/llvm/llvm-project into rang…
jamesETsmith Oct 7, 2023
a455f42
[libc++] Implement ranges::iota: Adding helper function to implementa…
jamesETsmith Oct 25, 2023
08e3c77
[libc++] Implement ranges::iota: Adding tests to ranges_robust_agains…
jamesETsmith Oct 26, 2023
e658ec2
[libc++] Implement ranges::iota: Merging with main and handling confl…
jamesETsmith Oct 26, 2023
67fcac1
[libc++] Implement ranges::iota: Fixing formatting problems
jamesETsmith Oct 26, 2023
b132784
[libc++] Implement ranges::iota: Addressing comments about out_value_…
jamesETsmith Oct 26, 2023
88e271a
[libc++] Implement ranges::iota: Updating Proxy<T> in test_iterators.…
jamesETsmith Oct 27, 2023
ff5bf79
[libc++] Implement ranges::iota: Fixing some of the buildkite errors,…
jamesETsmith Oct 28, 2023
b8f07b8
[libc++] Implement ranges::iota: Explicitly adding #include for range…
jamesETsmith Oct 30, 2023
a4d34fd
[libc++] Implement ranges::iota: Explicitly adding #include for range…
jamesETsmith Oct 30, 2023
334088f
:Merge branch 'main' of https://github.com/llvm/llvm-project into ran…
jamesETsmith Oct 30, 2023
8153244
[libc++] Implement ranges::iota: Adding #ifdef _LIBCPP_STD_VER >= 23 …
jamesETsmith Oct 31, 2023
5889be3
test commit
boomanaiden154 Nov 12, 2023
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
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_ranges_chunk_by`` ``202202L``
--------------------------------------------------- -----------------
``__cpp_lib_ranges_iota`` *unimplemented*
``__cpp_lib_ranges_iota`` ``202202L``
--------------------------------------------------- -----------------
``__cpp_lib_ranges_join_with`` *unimplemented*
--------------------------------------------------- -----------------
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"`P2255R2 <https://wg21.link/P2255R2>`__","LWG","A type trait to detect reference binding to temporary","February 2022","",""
"`P2273R3 <https://wg21.link/P2273R3>`__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0"
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","|In progress|","","|ranges|"
"`P2441R2 <https://wg21.link/P2441R2>`__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|"
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"
"`P2443R1 <https://wg21.link/P2443R1>`__","LWG","``views::chunk_by``","February 2022","|Complete|","18.0","|ranges|"
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/RangesAlgorithms.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ C++23,`shift_right <https://wg21.link/p2440r1>`_,Unassigned,No patch yet,Not sta
C++23,`iota (algorithm) <https://wg21.link/p2440r1>`_,Unassigned,No patch yet,Not started
C++23,`fold <https://wg21.link/p2322r5>`_,Unassigned,No patch yet,Not started
C++23,`contains <https://wg21.link/p2302r2>`_,Zijun Zhao,No patch yet,In Progress
C++23,`ranges::iota <https://wg21.link/P2440R1>`_, James E T Smith, `PR68494 <https://github.com/llvm/llvm-project/pull/68494>`_, In Progress
1 change: 1 addition & 0 deletions libcxx/docs/Status/RangesMajorFeatures.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ Standard,Name,Assignee,CL,Status
C++23,`ranges::to <https://wg21.link/P1206R7>`_,Konstantin Varlamov,`D142335 <https://reviews.llvm.org/D142335>`_,Complete
C++23,`Pipe support for user-defined range adaptors <https://wg21.link/P2387R3>`_,Unassigned,No patch yet,Not started
C++23,`Formatting Ranges <https://wg21.link/P2286R8>`_,Mark de Wever,Various,Complete
C++23, `ranges::iota <https://wg21.link/P2440R1>`_, James E T Smith, `PR68494 <https://github.com/llvm/llvm-project/pull/68494>`_, In Progress
C++20,`Stashing stashing iterators for proper flattening <https://wg21.link/P2770R0>`_,Jakub Mazurkiewicz,Various,In progress
2 changes: 2 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ set(files
__algorithm/next_permutation.h
__algorithm/none_of.h
__algorithm/nth_element.h
__algorithm/out_value_result.h
__algorithm/partial_sort.h
__algorithm/partial_sort_copy.h
__algorithm/partition.h
Expand Down Expand Up @@ -564,6 +565,7 @@ set(files
__numeric/partial_sum.h
__numeric/pstl_reduce.h
__numeric/pstl_transform_reduce.h
__numeric/ranges_iota.h
__numeric/reduce.h
__numeric/transform_exclusive_scan.h
__numeric/transform_inclusive_scan.h
Expand Down
56 changes: 56 additions & 0 deletions libcxx/include/__algorithm/out_value_result.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
#define _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H

#include <__concepts/convertible_to.h>
#include <__config>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23

namespace ranges {

template <class _OutIter1, class _ValType1>
struct out_value_result {
_LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
_LIBCPP_NO_UNIQUE_ADDRESS _ValType1 value;

template <class _OutIter2, class _ValType2>
requires convertible_to<const _OutIter1&, _OutIter2> && convertible_to<const _ValType1&, _ValType2>
_LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() const& {
return {out, value};
}

template <class _OutIter2, class _ValType2>
requires convertible_to<_OutIter1, _OutIter2> && convertible_to<_ValType1, _ValType2>
_LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() && {
return {std::move(out), std::move(value)};
}
};

} // namespace ranges

#endif // _LIBCPP_STD_VER >= 23

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
71 changes: 71 additions & 0 deletions libcxx/include/__numeric/ranges_iota.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___NUMERIC_RANGES_IOTA_H
#define _LIBCPP___NUMERIC_RANGES_IOTA_H

#include <__algorithm/out_value_result.h>
#include <__config>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__utility/as_const.h>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23
namespace ranges {
template <typename _Out, typename _Tp>
using iota_result = ranges::out_value_result<_Out, _Tp>;

namespace __ranges_iota {
struct __iota_fn {
private:
// Private helper function
template <class _Out, class _Sent, class _Tp>
_LIBCPP_HIDE_FROM_ABI static constexpr iota_result<_Out, _Tp> __iota_impl(_Out __first, _Sent __last, _Tp __value) {
while (__first != __last) {
*__first = std::as_const(__value);
++__first;
++__value;
}
return {std::move(__first), std::move(__value)};
}

public:
// Public facing interfaces
template <input_or_output_iterator _Out, sentinel_for<_Out> _Sent, weakly_incrementable _Tp>
requires indirectly_writable<_Out, const _Tp&>
_LIBCPP_HIDE_FROM_ABI static constexpr iota_result<_Out, _Tp> operator()(_Out __first, _Sent __last, _Tp __value) {
return __iota_impl(std::move(__first), std::move(__last), std::move(__value));
}

template <weakly_incrementable _Tp, ranges::output_range<const _Tp&> _Range>
_LIBCPP_HIDE_FROM_ABI static constexpr iota_result<ranges::borrowed_iterator_t<_Range>, _Tp>
operator()(_Range&& __r, _Tp __value) {
return __iota_impl(ranges::begin(__r), ranges::end(__r), std::move(__value));
}
};
} // namespace __ranges_iota

inline namespace __cpo {
inline constexpr auto iota = __ranges_iota::__iota_fn{};
} // namespace __cpo
} // namespace ranges

#endif // _LIBCPP_STD_VER >= 23

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___NUMERIC_RANGES_IOTA_H
4 changes: 4 additions & 0 deletions libcxx/include/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ namespace ranges {
template <class I>
struct in_found_result; // since C++20

template <class O, class T>
struct out_value_result; // since C++23

template<forward_iterator I, sentinel_for<I> S, class Proj = identity,
indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> // since C++20
constexpr I min_element(I first, S last, Comp comp = {}, Proj proj = {});
Expand Down Expand Up @@ -1816,6 +1819,7 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/next_permutation.h>
#include <__algorithm/none_of.h>
#include <__algorithm/nth_element.h>
#include <__algorithm/out_value_result.h>
#include <__algorithm/partial_sort.h>
#include <__algorithm/partial_sort_copy.h>
#include <__algorithm/partition.h>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap.in
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,7 @@ module std_private_numeric_pstl_transform_reduce [system] {
export *
}
module std_private_numeric_reduce [system] { header "__numeric/reduce.h" }
module std_private_numeric_ranges_iota [system] { header "__numeric/ranges_iota.h" }
module std_private_numeric_transform_exclusive_scan [system] { header "__numeric/transform_exclusive_scan.h" }
module std_private_numeric_transform_inclusive_scan [system] { header "__numeric/transform_inclusive_scan.h" }
module std_private_numeric_transform_reduce [system] { header "__numeric/transform_reduce.h" }
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ template<class T>
#include <__numeric/partial_sum.h>
#include <__numeric/pstl_reduce.h>
#include <__numeric/pstl_transform_reduce.h>
#include <__numeric/ranges_iota.h>
#include <__numeric/reduce.h>
#include <__numeric/transform_exclusive_scan.h>
#include <__numeric/transform_inclusive_scan.h>
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# define __cpp_lib_ranges_as_rvalue 202207L
// # define __cpp_lib_ranges_chunk 202202L
# define __cpp_lib_ranges_chunk_by 202202L
// # define __cpp_lib_ranges_iota 202202L
# define __cpp_lib_ranges_iota 202202L
// # define __cpp_lib_ranges_join_with 202202L
# define __cpp_lib_ranges_repeat 202207L
// # define __cpp_lib_ranges_slide 202202L
Expand Down
4 changes: 3 additions & 1 deletion libcxx/modules/std/algorithm.inc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export namespace std {
using std::ranges::in_out_result;
// using std::ranges::in_value_result;
using std::ranges::min_max_result;
// using std::ranges::out_value_result;
#if _LIBCPP_STD_VER >= 23
using std::ranges::out_value_result;
#endif
} // namespace ranges

// [alg.nonmodifying], non-modifying sequence operations
Expand Down
8 changes: 6 additions & 2 deletions libcxx/modules/std/numeric.inc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ export namespace std {
using std::iota;

namespace ranges {
// using std::ranges::iota_result;
// using std::ranges::iota;

#if _LIBCPP_STD_VER >= 23
using std::ranges::iota;
using std::ranges::iota_result;
#endif // _LIBCPP_STD_VER >= 23

} // namespace ranges

// [numeric.ops.gcd], greatest common divisor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ static_assert(sizeof(std::ranges::in_out_out_result<Empty, Empty, char>) == 2);
static_assert(sizeof(std::ranges::in_out_out_result<int, Empty, Empty2>) == sizeof(int));
static_assert(sizeof(std::ranges::in_out_out_result<Empty, Empty, Empty>) == 3);

#if _LIBCPP_STD_VER >= 23
static_assert(sizeof(std::ranges::out_value_result<Empty, int>) == sizeof(int));
static_assert(sizeof(std::ranges::out_value_result<int, Empty>) == sizeof(int));
static_assert(sizeof(std::ranges::out_value_result<Empty, Empty>) == 2);
#endif
// In min_max_result both elements have the same type, so they can't have the same address.
// So the only way to test that [[no_unique_address]] is used is to have it in another struct
struct MinMaxNoUniqueAddress {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, C++20

// template <class O, class T>
// struct out_value_result;

#include <algorithm>
#include <cassert>
#include <type_traits>

#include "MoveOnly.h"

using std::ranges::out_value_result;

//
// Helper structs
//

// only explicit construction
struct IterTypeExplicit {
explicit IterTypeExplicit(int*);
};

// implicit construction
struct IterTypeImplicit {
IterTypeImplicit(int*);
};

struct IterTypeImplicitRef {
IterTypeImplicitRef(int&);
};

struct NotConvertible {};

template <class T>
struct ConvertibleFrom {
constexpr ConvertibleFrom(T c) : content{c} {}
T content;
};

// Standard layout classes can't have virtual functions
struct NonStandardLayoutTypeBase {
virtual ~NonStandardLayoutTypeBase();
};
struct NonStandardLayoutType : public NonStandardLayoutTypeBase {};

//
constexpr void test_constraints() {
// requires convertible_to<const _OutIter1&, _OutIter2> && convertible_to<const _ValType1&, _ValType2>
static_assert(std::is_constructible_v<out_value_result<int*, int>, out_value_result<int*, int>>);

// test failure when implicit conversion isn't allowed
static_assert(!std::is_constructible_v<out_value_result<IterTypeExplicit, int>, out_value_result<int*, int>>);

// test success when implicit conversion is allowed, checking combinations of value, reference, and const
static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>>);
static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const>);
static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int>&>);
static_assert(std::is_constructible_v<out_value_result<IterTypeImplicit, int>, out_value_result<int*, int> const&>);

static_assert(!std::is_constructible_v<out_value_result<IterTypeImplicitRef, int>, out_value_result<int, int>&>);

// has to be convertible via const&
static_assert(std::is_convertible_v<out_value_result<int, int>&, out_value_result<long, long>>);
static_assert(std::is_convertible_v<const out_value_result<int, int>&, out_value_result<long, long>>);
static_assert(std::is_convertible_v<out_value_result<int, int>&&, out_value_result<long, long>>);
static_assert(std::is_convertible_v<const out_value_result<int, int>&&, out_value_result<long, long>>);

// should be move constructible
static_assert(std::is_move_constructible_v<out_value_result<MoveOnly, int>>);
static_assert(std::is_move_constructible_v<out_value_result<int, MoveOnly>>);

// conversions should not work if there is no conversion
static_assert(!std::is_convertible_v<out_value_result<NotConvertible, int>, out_value_result<int, NotConvertible>>);
static_assert(!std::is_convertible_v<out_value_result<int, NotConvertible>, out_value_result<NotConvertible, int>>);

// check standard layout
static_assert(std::is_standard_layout_v<out_value_result<int, int>>);
static_assert(!std::is_standard_layout_v<out_value_result<NonStandardLayoutType, int>>);
}

// Test results
constexpr bool test() {
{
// Check that conversion operator works
out_value_result<double, int> res{10, 1};
assert(res.out == 10);
assert(res.value == 1);
out_value_result<ConvertibleFrom<double>, ConvertibleFrom<int>> res2 = res;
assert(res2.out.content == 10);
assert(res2.value.content == 1);
}
{
// Check that out_value_result isn't overconstrained w.r.t. move/copy constructors
out_value_result<MoveOnly, int> res{MoveOnly{}, 10};
assert(res.out.get() == 1);
assert(res.value == 10);
auto res2 = std::move(res);
assert(res.out.get() == 0);
assert(res.value == 10);
assert(res2.out.get() == 1);
assert(res2.value == 10);
}
{
// Check structured binding
auto [out, val] = out_value_result<int, int>{1, 2};
assert(out == 1);
assert(val == 2);
}
{
// Check default construction
out_value_result<int, double> res;
static_assert(std::is_same_v<int, decltype(res.out)>);
static_assert(std::is_same_v<double, decltype(res.value)>);
}
{
// Check aggregate initiazliation
out_value_result<int, int> res = {1, 2};
assert(res.out == 1);
assert(res.value == 2);
}

return true;
}

int main(int, char**) {
test_constraints();
test();
static_assert(test());
return 0;
}
Loading
Loading