Skip to content

Commit

Permalink
[libc++] Implements ranges::enable_borrowed_range
Browse files Browse the repository at this point in the history
This is the initial patch to implement ranges in libc++.

Implements parts of:
- P0896R4 One Ranges Proposal
- P1870 forwarding-range is too subtle
- LWG3379 in several library names is misleading

Reviewed By: ldionne, #libc, cjdb, zoecarver, Quuxplusone

Differential Revision: https://reviews.llvm.org/D90999
  • Loading branch information
mordante committed Apr 18, 2021
1 parent aa80ea8 commit 01ace07
Show file tree
Hide file tree
Showing 18 changed files with 379 additions and 4 deletions.
2 changes: 1 addition & 1 deletion libcxx/docs/Cxx2aStatusIssuesStatus.csv
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@
"`3374 <https://wg21.link/LWG3374>`__","P0653 + P1006 should have made the other ``std::to_address``\ overload ``constexpr``\ ","Prague","|Complete|","12.0"
"`3375 <https://wg21.link/LWG3375>`__","``decay``\ in ``viewable_range``\ should be ``remove_cvref``\ ","Prague","",""
"`3377 <https://wg21.link/LWG3377>`__","``elements_view::iterator``\ befriends a specialization of itself","Prague","",""
"`3379 <https://wg21.link/LWG3379>`__","""``safe``\ "" in several library names is misleading","Prague","",""
"`3379 <https://wg21.link/LWG3379>`__","""``safe``\ "" in several library names is misleading","Prague","|In Progress|",""
"`3380 <https://wg21.link/LWG3380>`__","``common_type``\ and comparison categories","Prague","",""
"`3381 <https://wg21.link/LWG3381>`__","``begin``\ and ``data``\ must agree for ``contiguous_range``\ ","Prague","",""
"`3382 <https://wg21.link/LWG3382>`__","NTTP for ``pair``\ and ``array``\ ","Prague","",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Cxx2aStatusPaperStatus.csv
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
"`P1862 <https://wg21.link/P1862>`__","LWG","Ranges adaptors for non-copyable iterators","Belfast","* *",""
"`P1865 <https://wg21.link/P1865>`__","LWG","Add max() to latch and barrier","Belfast","|Complete|","11.0"
"`P1869 <https://wg21.link/P1869>`__","LWG","Rename 'condition_variable_any' interruptible wait methods","Belfast","* *",""
"`P1870 <https://wg21.link/P1870>`__","LWG","forwarding-range is too subtle","Belfast","* *",""
"`P1870 <https://wg21.link/P1870>`__","LWG","forwarding-range is too subtle","Belfast","|In Progress|",""
"`P1871 <https://wg21.link/P1871>`__","LWG","Should concepts be enabled or disabled?","Belfast","* *",""
"`P1872 <https://wg21.link/P1872>`__","LWG","span should have size_type, not index_type","Belfast","|Complete|","10.0"
"`P1878 <https://wg21.link/P1878>`__","LWG","Constraining Readable Types","Belfast","* *",""
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(files
__mutex_base
__node_handle
__nullptr
__ranges/enable_borrowed_range.h
__split_buffer
__sso_allocator
__std_stream
Expand Down Expand Up @@ -141,6 +142,7 @@ set(files
ostream
queue
random
ranges
ratio
regex
scoped_allocator
Expand Down
46 changes: 46 additions & 0 deletions libcxx/include/__ranges/enable_borrowed_range.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// -*- C++ -*-
//===------------------ __ranges/enable_borrowed_range.h ------------------===//
//
// 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___RANGES_ENABLE_BORROWED_RANGE_H
#define _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H

// These customization variables are used in <span> and <string_view>. The
// separate header is used to avoid including the entire <ranges> header in
// <span> and <string_view>.

#include <__config>

#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 > 17 && !defined(_LIBCPP_HAS_NO_RANGES)

namespace ranges
{

// [range.range], ranges

template <class>
inline constexpr bool enable_borrowed_range = false;

} // namespace ranges

#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H
4 changes: 4 additions & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ module std [system] {
export initializer_list
export *
}
module ranges {
header "ranges"
export *
}
module ratio {
header "ratio"
export *
Expand Down
52 changes: 52 additions & 0 deletions libcxx/include/ranges
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// -*- C++ -*-
//===--------------------------- ranges -----------------------------------===//
//
// 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_RANGES
#define _LIBCPP_RANGES

/*
#include <compare> // see [compare.syn]
#include <initializer_list> // see [initializer.list.syn]
#include <iterator> // see [iterator.synopsis]
namespace std::ranges {
// [range.range], ranges
template<class T>
inline constexpr bool enable_borrowed_range = false;
}
*/

#include <__config>
#include <__ranges/enable_borrowed_range.h>
#include <compare> // Required by the standard.
#include <initializer_list> // Required by the standard.
#include <iterator> // Required by the standard.
#include <type_traits>
#include <version>

#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 > 17 && !defined(_LIBCPP_HAS_NO_RANGES)

#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP_RANGES
10 changes: 9 additions & 1 deletion libcxx/include/span
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
template <class ElementType, size_t Extent = dynamic_extent>
class span;
template<class ElementType, size_t Extent>
inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
// [span.objectrep], views of object representation
template <class ElementType, size_t Extent>
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
Expand All @@ -32,7 +35,6 @@ template <class ElementType, size_t Extent>
(sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
namespace std {
template <class ElementType, size_t Extent = dynamic_extent>
class span {
public:
Expand Down Expand Up @@ -123,6 +125,7 @@ template<class Container>
*/

#include <__config>
#include <__ranges/enable_borrowed_range.h>
#include <array> // for array
#include <cstddef> // for byte
#include <iterator> // for iterators
Expand Down Expand Up @@ -516,6 +519,11 @@ private:
size_type __size;
};

#if !defined(_LIBCPP_HAS_NO_RANGES)
template <class _Tp, size_t _Extent>
inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true;
#endif // !defined(_LIBCPP_HAS_NO_RANGES)

// as_bytes & as_writable_bytes
template <class _Tp, size_t _Extent>
_LIBCPP_INLINE_VISIBILITY
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/string_view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ namespace std {
template<class charT, class traits = char_traits<charT>>
class basic_string_view;
template<class charT, class traits>
inline constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // C++20
// 7.9, basic_string_view non-member comparison functions
template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> x,
Expand Down Expand Up @@ -179,6 +182,7 @@ namespace std {
*/

#include <__config>
#include <__ranges/enable_borrowed_range.h>
#include <__string>
#include <iosfwd>
#include <algorithm>
Expand Down Expand Up @@ -649,6 +653,10 @@ private:
size_type __size;
};

#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
template <class _CharT, class _Traits>
inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true;
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)

// [string.view.comparison]
// operator ==
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/double_include.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
#endif
#include <queue>
#include <random>
#include <ranges>
#include <ratio>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <regex>
Expand Down
34 changes: 34 additions & 0 deletions libcxx/test/libcxx/inclusions/ranges.inclusions.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// WARNING: This test was generated by generate_header_inclusion_tests.py
// and should not be edited manually.
//
// clang-format off

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

// <ranges>

// Test that <ranges> includes all the other headers it's supposed to.

#include <ranges>
#include "test_macros.h"

#if !defined(_LIBCPP_RANGES)
# error "<ranges> was expected to define _LIBCPP_RANGES"
#endif
#if TEST_STD_VER > 17 && !defined(_LIBCPP_COMPARE)
# error "<ranges> should include <compare> in C++20 and later"
#endif
#if TEST_STD_VER > 03 && !defined(_LIBCPP_INITIALIZER_LIST)
# error "<ranges> should include <initializer_list> in C++20 and later"
#endif
#if !defined(_LIBCPP_ITERATOR)
# error "<ranges> should include <iterator> in C++20 and later"
#endif
2 changes: 2 additions & 0 deletions libcxx/test/libcxx/min_max_macros.compile.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ TEST_MACROS();
TEST_MACROS();
#include <random>
TEST_MACROS();
#include <ranges>
TEST_MACROS();
#include <ratio>
TEST_MACROS();
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
Expand Down
1 change: 1 addition & 0 deletions libcxx/test/libcxx/no_assert_include.compile.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
#endif
#include <queue>
#include <random>
#include <ranges>
#include <ratio>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <regex>
Expand Down
20 changes: 20 additions & 0 deletions libcxx/test/libcxx/ranges/version.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// <ranges>

#include <ranges>

#include "test_macros.h"

#ifndef _LIBCPP_VERSION
#error _LIBCPP_VERSION not defined
#endif

// Required for MSVC internal test runner compatibility.
int main(int, char**) { return 0; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts

// <span>

// template<class ElementType, size_t Extent>
// inline constexpr bool ranges::enable_borrowed_range<
// span<ElementType, Extent>> = true;

#include <span>

#include "test_macros.h"

void test() {
static_assert(std::ranges::enable_borrowed_range<std::span<int, 0> >);
static_assert(std::ranges::enable_borrowed_range<std::span<int, 42> >);
static_assert(std::ranges::enable_borrowed_range<std::span<int, std::dynamic_extent> >);
static_assert(!std::ranges::enable_borrowed_range<std::span<int, 42>&>);
static_assert(!std::ranges::enable_borrowed_range<std::span<int, 42> const>);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// WARNING: This test was generated by generate_feature_test_macro_components.py
// and should not be edited manually.
//
// clang-format off

// <ranges>

// Test the feature test macros defined by <ranges>

/* Constant Value
__cpp_lib_ranges 201811L [C++20]
*/

#include <ranges>
#include "test_macros.h"

#if TEST_STD_VER < 14

# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

#elif TEST_STD_VER == 14

# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

#elif TEST_STD_VER == 17

# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

#elif TEST_STD_VER == 20

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++20"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++20"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# endif
# endif

#elif TEST_STD_VER > 20

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges
# error "__cpp_lib_ranges should be defined in c++2b"
# endif
# if __cpp_lib_ranges != 201811L
# error "__cpp_lib_ranges should have the value 201811L in c++2b"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges
# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
# endif
# endif

#endif // TEST_STD_VER > 20

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

0 comments on commit 01ace07

Please sign in to comment.