Skip to content

Commit

Permalink
[libcxx][ranges] implements dangling, borrowed_iterator_t, borrowed_s…
Browse files Browse the repository at this point in the history
…ubrange_t

* Implements part of P0896 'The One Ranges Proposal'
* Implements http://wg21.link/range.dangling

Reviewed By: zoecarver

Differential Revision: https://reviews.llvm.org/D105205
  • Loading branch information
cjdb committed Jul 21, 2021
1 parent 0082764 commit 74fd3cb
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 1 deletion.
2 changes: 1 addition & 1 deletion libcxx/docs/Status/RangesPaper.csv
Expand Up @@ -133,7 +133,7 @@ Section,Description,Dependencies,Assignee,Complete
`[range.dangling] <http://wg21.link/range.dangling>`_,"| ranges::dangling
| ranges::borrowed_iterator_t
| ranges::borrowed_subrange_t","| [range.range]
| [range.subrange]",Unassigned,Not started
| [range.subrange]",Christopher Di Bella,✅
`[range.all] <http://wg21.link/range.all>`_,`view::all <https://llvm.org/D102028>`_,"[range.subrange], [range.view.ref]",Zoe Carver,✅
`[range.view.ref] <http://wg21.link/range.view>`_,`ref-view <https://llvm.org/D102020>`_,[view.interface],Zoe Carver,✅
`[range.filter] <http://wg21.link/range.filter>`_,filter_view,[range.all],Louis Dionne,Not started
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Expand Up @@ -186,6 +186,7 @@ set(files
__ranges/all.h
__ranges/concepts.h
__ranges/copyable_box.h
__ranges/dangling.h
__ranges/data.h
__ranges/drop_view.h
__ranges/empty_view.h
Expand Down
47 changes: 47 additions & 0 deletions libcxx/include/__ranges/dangling.h
@@ -0,0 +1,47 @@
// -*- 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___RANGES_DANGLING_H
#define _LIBCPP___RANGES_DANGLING_H

#include <__config>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <type_traits>

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

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if !defined(_LIBCPP_HAS_NO_RANGES)

namespace ranges {
struct dangling {
dangling() = default;
_LIBCPP_HIDE_FROM_ABI constexpr dangling(auto&&...) noexcept {}
};

template <range _Rp>
using borrowed_iterator_t = _If<borrowed_range<_Rp>, iterator_t<_Rp>, dangling>;

// borrowed_subrange_t defined in <__ranges/subrange.h>
} // namespace ranges

#endif // !_LIBCPP_HAS_NO_RANGES

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___RANGES_DANGLING_H
4 changes: 4 additions & 0 deletions libcxx/include/__ranges/subrange.h
Expand Up @@ -16,6 +16,7 @@
#include <__iterator/advance.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__ranges/enable_borrowed_range.h>
#include <__ranges/size.h>
#include <__ranges/view_interface.h>
Expand Down Expand Up @@ -248,6 +249,9 @@ namespace ranges {

template<class _Ip, class _Sp, subrange_kind _Kp>
inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;

template<range _Rp>
using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp> >, dangling>;
} // namespace ranges

using ranges::get;
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Expand Up @@ -606,6 +606,7 @@ module std [system] {
module all { private header "__ranges/all.h" }
module concepts { private header "__ranges/concepts.h" }
module copyable_box { private header "__ranges/copyable_box.h" }
module dangling { private header "__ranges/dangling.h" }
module data { private header "__ranges/data.h" }
module drop_view { private header "__ranges/drop_view.h" }
module empty { private header "__ranges/empty.h" }
Expand Down
10 changes: 10 additions & 0 deletions libcxx/include/ranges
Expand Up @@ -103,6 +103,15 @@ namespace std::ranges {
template<class I, class S, subrange_kind K>
inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
// [range.dangling], dangling iterator handling
struct dangling;
template<range R>
using borrowed_iterator_t = see below;
template<range R>
using borrowed_subrange_t = see below;
// [range.empty], empty view
template<class T>
requires is_object_v<T>
Expand Down Expand Up @@ -145,6 +154,7 @@ namespace std::ranges {
#include <__ranges/access.h>
#include <__ranges/all.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__ranges/data.h>
#include <__ranges/drop_view.h>
#include <__ranges/empty.h>
Expand Down
@@ -0,0 +1,16 @@
// -*- 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
//
//===----------------------------------------------------------------------===//

// REQUIRES: modules-build

// WARNING: This test was generated by 'generate_private_header_tests.py'
// and should not be edited manually.

// expected-error@*:* {{use of private header from outside its module: '__ranges/dangling.h'}}
#include <__ranges/dangling.h>
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: gcc-10

// std::ranges::borrowed_iterator_t;

#include <ranges>

#include <concepts>
#include <span>
#include <string>
#include <string_view>
#include <vector>

static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string>, std::ranges::dangling>);
static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string&&>, std::ranges::dangling>);
static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::vector<int> >, std::ranges::dangling>);

static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string&>, std::string::iterator>);
static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::string_view>, std::string_view::iterator>);
static_assert(std::same_as<std::ranges::borrowed_iterator_t<std::span<int> >, std::span<int>::iterator>);

template <class T>
constexpr bool has_borrowed_iterator = requires {
typename std::ranges::borrowed_iterator_t<T>;
};

static_assert(!has_borrowed_iterator<int>);
@@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: gcc-10

// std::ranges::borrowed_subrange_t;

#include <ranges>

#include <concepts>
#include <span>
#include <string>
#include <string_view>
#include <vector>

static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string>, std::ranges::dangling>);
static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string&&>, std::ranges::dangling>);
static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::vector<int> >, std::ranges::dangling>);

static_assert(
std::same_as<std::ranges::borrowed_subrange_t<std::string&>, std::ranges::subrange<std::string::iterator> >);

static_assert(
std::same_as<std::ranges::borrowed_subrange_t<std::span<int> >, std::ranges::subrange<std::span<int>::iterator> >);

static_assert(std::same_as<std::ranges::borrowed_subrange_t<std::string_view>,
std::ranges::subrange<std::string_view::iterator> >);

template <class T>
constexpr bool has_type = requires {
typename std::ranges::borrowed_subrange_t<T>;
};

static_assert(!has_type<int>);

struct S {};
static_assert(!has_type<S>);
@@ -0,0 +1,40 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: gcc-10

// std::ranges::dangling;

#include <ranges>

#include <concepts>
#include <type_traits>

static_assert(std::is_empty_v<std::ranges::dangling>);

template<int> struct S { };
static_assert(std::is_nothrow_constructible_v<std::ranges::dangling>);
static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>>);
static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>, S<1>>);
static_assert(std::is_nothrow_constructible_v<std::ranges::dangling, S<0>, S<1>, S<2>>);

constexpr bool test_dangling() {
[[maybe_unused]] auto a = std::ranges::dangling();
[[maybe_unused]] auto b = std::ranges::dangling(S<0>());
[[maybe_unused]] auto c = std::ranges::dangling(S<0>(), S<1>());
[[maybe_unused]] auto d = std::ranges::dangling(S<0>(), S<1>(), S<2>());
return true;
}

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

0 comments on commit 74fd3cb

Please sign in to comment.