forked from OSchip/llvm-project
[libcxx][ranges] adds `range` access CPOs
* `std::ranges::begin` * `std::ranges::cbegin` * `std::ranges::end` * `std::ranges::cend` * `std::ranges::iterator` (required for `end`) Implements parts of: * P0896R4 The One Ranges Proposal` Co-author: @zoecarver Depends on D90999, D100160. Differential Revision: https://reviews.llvm.org/D100255
This commit is contained in:
parent
a3fd82c289
commit
5a3309f825
|
@ -35,6 +35,7 @@ set(files
|
|||
__mutex_base
|
||||
__node_handle
|
||||
__nullptr
|
||||
__ranges/access.h
|
||||
__ranges/enable_borrowed_range.h
|
||||
__split_buffer
|
||||
__sso_allocator
|
||||
|
@ -150,6 +151,7 @@ set(files
|
|||
random
|
||||
ranges
|
||||
ratio
|
||||
ranges
|
||||
regex
|
||||
scoped_allocator
|
||||
semaphore
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
// -*- C++ -*-
|
||||
//===------------------------ __ranges/begin.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_ACCESS_H
|
||||
#define _LIBCPP___RANGES_ACCESS_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__ranges/enable_borrowed_range.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)
|
||||
|
||||
// clang-format off
|
||||
|
||||
namespace ranges {
|
||||
template <class _Tp>
|
||||
concept __can_borrow =
|
||||
is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp> >;
|
||||
|
||||
template<class _Tp>
|
||||
concept __is_complete = requires { sizeof(_Tp); };
|
||||
} // namespace ranges
|
||||
|
||||
// [range.access.begin]
|
||||
namespace ranges::__begin {
|
||||
template <class _Tp>
|
||||
concept __member_begin =
|
||||
__can_borrow<_Tp> &&
|
||||
requires(_Tp&& __t) {
|
||||
{ _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator;
|
||||
};
|
||||
|
||||
void begin(auto&) = delete;
|
||||
void begin(const auto&) = delete;
|
||||
|
||||
template <class _Tp>
|
||||
concept __unqualified_begin =
|
||||
!__member_begin<_Tp> &&
|
||||
__can_borrow<_Tp> &&
|
||||
__class_or_enum<remove_cvref_t<_Tp> > &&
|
||||
requires(_Tp && __t) {
|
||||
{ _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator;
|
||||
};
|
||||
|
||||
struct __fn {
|
||||
template <class _Tp>
|
||||
requires is_array_v<remove_cv_t<_Tp>>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp& __t) const noexcept {
|
||||
constexpr bool __complete = __is_complete<iter_value_t<_Tp> >;
|
||||
if constexpr (__complete) { // used to disable cryptic diagnostic
|
||||
return __t + 0;
|
||||
}
|
||||
else {
|
||||
static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type.");
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires __member_begin<_Tp>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(_VSTD::__decay_copy(__t.begin())))
|
||||
{
|
||||
return __t.begin();
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires __unqualified_begin<_Tp>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(_VSTD::__decay_copy(begin(__t))))
|
||||
{
|
||||
return begin(__t);
|
||||
}
|
||||
|
||||
void operator()(auto&&) const = delete;
|
||||
};
|
||||
} // namespace ranges::__begin
|
||||
|
||||
namespace ranges {
|
||||
inline namespace __cpo {
|
||||
inline constexpr auto begin = __begin::__fn{};
|
||||
} // namespace __cpo
|
||||
|
||||
template <class _Tp>
|
||||
using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
|
||||
} // namespace ranges
|
||||
|
||||
// [range.access.end]
|
||||
namespace ranges::__end {
|
||||
template <class _Tp>
|
||||
concept __member_end =
|
||||
__can_borrow<_Tp> &&
|
||||
requires(_Tp&& __t) {
|
||||
typename iterator_t<_Tp>;
|
||||
{ _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >;
|
||||
};
|
||||
|
||||
void end(auto&) = delete;
|
||||
void end(const auto&) = delete;
|
||||
|
||||
template <class _Tp>
|
||||
concept __unqualified_end =
|
||||
!__member_end<_Tp> &&
|
||||
__can_borrow<_Tp> &&
|
||||
__class_or_enum<remove_cvref_t<_Tp> > &&
|
||||
requires(_Tp && __t) {
|
||||
typename iterator_t<_Tp>;
|
||||
{ _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >;
|
||||
};
|
||||
|
||||
class __fn {
|
||||
public:
|
||||
template <class _Tp, size_t _Np>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept {
|
||||
constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >;
|
||||
if constexpr (__complete) { // used to disable cryptic diagnostic
|
||||
return __t + _Np;
|
||||
}
|
||||
else {
|
||||
static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type.");
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires __member_end<_Tp>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(_VSTD::__decay_copy(__t.end())))
|
||||
{
|
||||
return _VSTD::forward<_Tp>(__t).end();
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires __unqualified_end<_Tp>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(_VSTD::__decay_copy(end(__t))))
|
||||
{
|
||||
return end(__t);
|
||||
}
|
||||
|
||||
void operator()(auto&&) const = delete;
|
||||
};
|
||||
} // namespace ranges::__end
|
||||
|
||||
namespace ranges::inline __cpo {
|
||||
inline constexpr auto end = __end::__fn{};
|
||||
} // namespace ranges::__cpo
|
||||
|
||||
namespace ranges::__cbegin {
|
||||
struct __fn {
|
||||
template <class _Tp>
|
||||
requires invocable<decltype(ranges::begin), _Tp const&>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp& __t) const
|
||||
noexcept(noexcept(ranges::begin(_VSTD::as_const(__t))))
|
||||
{
|
||||
return ranges::begin(_VSTD::as_const(__t));
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t))))
|
||||
{
|
||||
return ranges::begin(static_cast<_Tp const&&>(__t));
|
||||
}
|
||||
};
|
||||
} // namespace ranges::__cbegin
|
||||
|
||||
namespace ranges::inline __cpo {
|
||||
inline constexpr auto cbegin = __cbegin::__fn{};
|
||||
} // namespace ranges::__cpo
|
||||
|
||||
namespace ranges::__cend {
|
||||
struct __fn {
|
||||
template <class _Tp>
|
||||
requires invocable<decltype(ranges::end), _Tp const&>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp& __t) const
|
||||
noexcept(noexcept(ranges::end(_VSTD::as_const(__t))))
|
||||
{
|
||||
return ranges::end(_VSTD::as_const(__t));
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&>
|
||||
[[nodiscard]] constexpr auto operator()(_Tp&& __t) const
|
||||
noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t))))
|
||||
{
|
||||
return ranges::end(static_cast<_Tp const&&>(__t));
|
||||
}
|
||||
};
|
||||
} // namespace ranges::__cend
|
||||
|
||||
namespace ranges::inline __cpo {
|
||||
inline constexpr auto cend = __cend::__fn{};
|
||||
} // namespace ranges::__cpo
|
||||
|
||||
// clang-format off
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___RANGES_ACCESS_H
|
|
@ -411,6 +411,9 @@ module std [system] {
|
|||
}
|
||||
module ranges {
|
||||
header "ranges"
|
||||
export compare
|
||||
export initializer_list
|
||||
export iterator
|
||||
export *
|
||||
}
|
||||
module ratio {
|
||||
|
|
|
@ -17,14 +17,26 @@
|
|||
#include <iterator> // see [iterator.synopsis]
|
||||
|
||||
namespace std::ranges {
|
||||
inline namespace unspecified {
|
||||
// [range.access], range access
|
||||
inline constexpr unspecified begin = unspecified;
|
||||
inline constexpr unspecified end = unspecified;
|
||||
inline constexpr unspecified cbegin = unspecified;
|
||||
inline constexpr unspecified cend = unspecified;
|
||||
}
|
||||
|
||||
// [range.range], ranges
|
||||
template<class T>
|
||||
inline constexpr bool enable_borrowed_range = false;
|
||||
|
||||
template<class T>
|
||||
using iterator_t = decltype(ranges::begin(declval<T&>()));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <__ranges/access.h>
|
||||
#include <__ranges/enable_borrowed_range.h>
|
||||
#include <compare> // Required by the standard.
|
||||
#include <initializer_list> // Required by the standard.
|
||||
|
|
|
@ -2814,6 +2814,9 @@ template <class _Tp>
|
|||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename decay<_Tp>::type
|
||||
__decay_copy(_Tp&& __t)
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp>>)
|
||||
#endif
|
||||
{
|
||||
return _VSTD::forward<_Tp>(__t);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// map
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::map<int, int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// multimap
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::multimap<int, int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// multiset
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::multiset<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// set
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::set<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// array
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::array<int, 10>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// deque
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::deque<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// forward_list
|
||||
|
||||
#include <forward_list>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::forward_list<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// list
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::list<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// vector
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::vector<bool>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// vector
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::vector<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unordered_map
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::unordered_map<int, int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unordered_multimap
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::unordered_multimap<int, int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unordered_multiset
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::unordered_multiset<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,25 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unordered_multiset
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::unordered_set<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// span
|
||||
|
||||
#include <span>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
using range = std::span<int>;
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<range>, range::iterator>);
|
|
@ -0,0 +1,26 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// directory_iterator, recursive_directory_iterator
|
||||
|
||||
#include "filesystem_include.h"
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::directory_iterator>, fs::directory_iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::directory_iterator const>, fs::directory_iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator>, fs::recursive_directory_iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator const>, fs::recursive_directory_iterator>);
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// path
|
||||
|
||||
#include "filesystem_include.h"
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::path>, fs::path::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<fs::path const>, fs::path::const_iterator>);
|
|
@ -0,0 +1,263 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// std::ranges::begin
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <cassert>
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
using RangeBeginT = decltype(std::ranges::begin)&;
|
||||
using RangeCBeginT = decltype(std::ranges::cbegin)&;
|
||||
|
||||
static int globalBuff[8];
|
||||
|
||||
struct Incomplete;
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[10]>);
|
||||
static_assert( std::is_invocable_v<RangeBeginT, int (&)[10]>);
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[]>);
|
||||
static_assert( std::is_invocable_v<RangeBeginT, int (&)[]>);
|
||||
|
||||
struct BeginMember {
|
||||
int x;
|
||||
constexpr const int *begin() const { return &x; }
|
||||
};
|
||||
|
||||
// Ensure that we can't call with rvalues with borrowing disabled.
|
||||
static_assert( std::is_invocable_v<RangeBeginT, BeginMember &>);
|
||||
static_assert( std::is_invocable_v<RangeBeginT, BeginMember const&>);
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginMember &&>);
|
||||
static_assert( std::is_invocable_v<RangeCBeginT, BeginMember &>);
|
||||
static_assert( std::is_invocable_v<RangeCBeginT, BeginMember const&>);
|
||||
|
||||
constexpr bool testArray() {
|
||||
int a[2];
|
||||
assert(std::ranges::begin(a) == a);
|
||||
assert(std::ranges::cbegin(a) == a);
|
||||
|
||||
int b[2][2];
|
||||
assert(std::ranges::begin(b) == b);
|
||||
assert(std::ranges::cbegin(b) == b);
|
||||
|
||||
BeginMember c[2];
|
||||
assert(std::ranges::begin(c) == c);
|
||||
assert(std::ranges::cbegin(c) == c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct BeginMemberFunction {
|
||||
int x;
|
||||
constexpr const int *begin() const { return &x; }
|
||||
friend constexpr int *begin(BeginMemberFunction const& bf);
|
||||
};
|
||||
|
||||
struct BeginMemberReturnsInt {
|
||||
int begin() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsInt const&>);
|
||||
|
||||
struct BeginMemberReturnsVoidPtr {
|
||||
const void *begin() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsVoidPtr const&>);
|
||||
|
||||
struct Empty { };
|
||||
struct EmptyBeginMember {
|
||||
Empty begin() const;
|
||||
};
|
||||
struct EmptyPtrBeginMember {
|
||||
Empty x;
|
||||
constexpr const Empty *begin() const { return &x; }
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, EmptyBeginMember const&>);
|
||||
|
||||
struct PtrConvertible {
|
||||
operator int*() const;
|
||||
};
|
||||
struct PtrConvertibleBeginMember {
|
||||
PtrConvertible begin() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, PtrConvertibleBeginMember const&>);
|
||||
|
||||
struct NonConstBeginMember {
|
||||
int x;
|
||||
constexpr int *begin() { return &x; }
|
||||
};
|
||||
|
||||
static_assert( std::is_invocable_v<RangeBeginT, NonConstBeginMember &>);
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, NonConstBeginMember const&>);
|
||||
static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember &>);
|
||||
static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember const&>);
|
||||
|
||||
struct EnabledBorrowingBeginMember {
|
||||
constexpr int *begin() const { return &globalBuff[0]; }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingBeginMember> = true;
|
||||
|
||||
constexpr bool testBeginMember() {
|
||||
BeginMember a;
|
||||
assert(std::ranges::begin(a) == &a.x);
|
||||
assert(std::ranges::cbegin(a) == &a.x);
|
||||
|
||||
NonConstBeginMember b;
|
||||
assert(std::ranges::begin(b) == &b.x);
|
||||
|
||||
EnabledBorrowingBeginMember c;
|
||||
assert(std::ranges::begin(std::move(c)) == &globalBuff[0]);
|
||||
|
||||
BeginMemberFunction d;
|
||||
assert(std::ranges::begin(d) == &d.x);
|
||||
assert(std::ranges::cbegin(d) == &d.x);
|
||||
|
||||
EmptyPtrBeginMember e;
|
||||
assert(std::ranges::begin(e) == &e.x);
|
||||
assert(std::ranges::cbegin(e) == &e.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct BeginFunction {
|
||||
int x;
|
||||
friend constexpr const int *begin(BeginFunction const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>);
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>);
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &>);
|
||||
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);
|
||||
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);
|
||||
|
||||
struct BeginFunctionWithDataMember {
|
||||
int x;
|
||||
int begin;
|
||||
friend constexpr const int *begin(BeginFunctionWithDataMember const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
struct BeginFunctionWithPrivateBeginMember : private BeginMember {
|
||||
int y;
|
||||
friend constexpr const int *begin(BeginFunctionWithPrivateBeginMember const& bf) { return &bf.y; }
|
||||
};
|
||||
|
||||
struct BeginFunctionReturnsEmptyPtr {
|
||||
Empty x;
|
||||
friend constexpr const Empty *begin(BeginFunctionReturnsEmptyPtr const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
struct BeginFunctionByValue {
|
||||
friend constexpr int *begin(BeginFunctionByValue) { return &globalBuff[1]; }
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeCBeginT, BeginFunctionByValue>);
|
||||
|
||||
struct BeginFunctionEnabledBorrowing {
|
||||
friend constexpr int *begin(BeginFunctionEnabledBorrowing) { return &globalBuff[2]; }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline constexpr bool std::ranges::enable_borrowed_range<BeginFunctionEnabledBorrowing> = true;
|
||||
|
||||
struct BeginFunctionReturnsInt {
|
||||
friend constexpr int begin(BeginFunctionReturnsInt const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsInt const&>);
|
||||
|
||||
struct BeginFunctionReturnsVoidPtr {
|
||||
friend constexpr void *begin(BeginFunctionReturnsVoidPtr const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsVoidPtr const&>);
|
||||
|
||||
struct BeginFunctionReturnsEmpty {
|
||||
friend constexpr Empty begin(BeginFunctionReturnsEmpty const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsEmpty const&>);
|
||||
|
||||
struct BeginFunctionReturnsPtrConvertible {
|
||||
friend constexpr PtrConvertible begin(BeginFunctionReturnsPtrConvertible const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsPtrConvertible const&>);
|
||||
|
||||
constexpr bool testBeginFunction() {
|
||||
const BeginFunction a{};
|
||||
assert(std::ranges::begin(a) == &a.x);
|
||||
BeginFunction aa{};
|
||||
assert(std::ranges::cbegin(aa) == &aa.x);
|
||||
|
||||
BeginFunctionByValue b;
|
||||
assert(std::ranges::begin(b) == &globalBuff[1]);
|
||||
assert(std::ranges::cbegin(b) == &globalBuff[1]);
|
||||
|
||||
BeginFunctionEnabledBorrowing c;
|
||||
assert(std::ranges::begin(std::move(c)) == &globalBuff[2]);
|
||||
|
||||
const BeginFunctionReturnsEmptyPtr d{};
|
||||
assert(std::ranges::begin(d) == &d.x);
|
||||
BeginFunctionReturnsEmptyPtr dd{};
|
||||
assert(std::ranges::cbegin(dd) == &dd.x);
|
||||
|
||||
const BeginFunctionWithDataMember e{};
|
||||
assert(std::ranges::begin(e) == &e.x);
|
||||
BeginFunctionWithDataMember ee{};
|
||||
assert(std::ranges::cbegin(ee) == &ee.x);
|
||||
|
||||
const BeginFunctionWithPrivateBeginMember f{};
|
||||
assert(std::ranges::begin(f) == &f.y);
|
||||
BeginFunctionWithPrivateBeginMember ff{};
|
||||
assert(std::ranges::cbegin(ff) == &ff.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct NoThrowMemberBegin {
|
||||
T begin() noexcept;
|
||||
T begin() const noexcept;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct NoThrowADLBegin {
|
||||
friend T begin(NoThrowADLBegin&) noexcept;
|
||||
friend T begin(NoThrowADLBegin const&) noexcept;
|
||||
};
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<int (&)[10]>()));
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberBegin<int*>&>()));
|
||||
ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberBegin<ThrowingIterator<int> >&>()));
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLBegin<int*>&>()));
|
||||
ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLBegin<ThrowingIterator<int> >&>()));
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
testArray();
|
||||
static_assert(testArray());
|
||||
|
||||
testBeginMember();
|
||||
static_assert(testBeginMember());
|
||||
|
||||
testBeginFunction();
|
||||
static_assert(testBeginFunction());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unspecified begin;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
using begin_t = decltype(std::ranges::begin);
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
requires(!std::invocable<begin_t&, T>)
|
||||
void f() {}
|
||||
// clang-format on
|
||||
|
||||
void test() {
|
||||
struct incomplete;
|
||||
f<incomplete(&)[]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[10]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[2][2]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
|
||||
// This is okay because calling `std::ranges::begin` on any rvalue is ill-formed.
|
||||
f<incomplete(&&)[10]>();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
// Tested in begin.pass.cpp.
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unspecified begin;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
using cbegin_t = decltype(std::ranges::cbegin);
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
requires(!std::invocable<cbegin_t&, T>)
|
||||
void f() {}
|
||||
// clang-format on
|
||||
|
||||
void test() {
|
||||
struct incomplete;
|
||||
f<incomplete(&)[]>();
|
||||
// expected-error@*:* {{"`std::ranges::cbegin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[10]>();
|
||||
// expected-error@*:* {{"`std::ranges::cbegin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[2][2]>();
|
||||
// expected-error@*:* {{"`std::ranges::cbegin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
|
||||
// This is okay because calling `std::ranges::cbegin` on any rvalue is ill-formed.
|
||||
f<incomplete(&&)[10]>();
|
||||
}
|
|
@ -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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// ranges::cbegin;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
using cbegin_t = decltype(std::ranges::cbegin);
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
requires(!std::invocable<cbegin_t&, T>)
|
||||
void f() {}
|
||||
// clang-format on
|
||||
|
||||
void test() {
|
||||
struct incomplete;
|
||||
f<incomplete(&)[10]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
|
||||
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
|
||||
f<incomplete(&&)[10]>();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
// Tested in end.pass.cpp.
|
|
@ -0,0 +1,43 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unspecified begin;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
using cend_t = decltype(std::ranges::cend);
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
requires(!std::invocable<cend_t&, T>)
|
||||
void f() {}
|
||||
// clang-format on
|
||||
|
||||
void test() {
|
||||
struct incomplete;
|
||||
f<incomplete(&)[]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
f<incomplete(&)[10]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-3 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[2][2]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
|
||||
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
|
||||
f<incomplete(&&)[10]>();
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// std::ranges::end
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <cassert>
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
using RangeEndT = decltype(std::ranges::end)&;
|
||||
using RangeCEndT = decltype(std::ranges::cend)&;
|
||||
|
||||
static int globalBuff[8];
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, int (&&)[]>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, int (&)[]>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, int (&&)[10]>);
|
||||
static_assert( std::is_invocable_v<RangeEndT, int (&)[10]>);
|
||||
|
||||
struct EndMember {
|
||||
int x;
|
||||
constexpr const int *begin() const { return nullptr; }
|
||||
constexpr const int *end() const { return &x; }
|
||||
};
|
||||
|
||||
// Ensure that we can't call with rvalues with borrowing disabled.
|
||||
static_assert( std::is_invocable_v<RangeEndT, EndMember &>);
|
||||
static_assert( std::is_invocable_v<RangeEndT, EndMember const&>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndMember &&>);
|
||||
static_assert( std::is_invocable_v<RangeCEndT, EndMember &>);
|
||||
static_assert( std::is_invocable_v<RangeCEndT, EndMember const&>);
|
||||
|
||||
constexpr bool testArray() {
|
||||
int a[2];
|
||||
assert(std::ranges::end(a) == a + 2);
|
||||
assert(std::ranges::cend(a) == a + 2);
|
||||
|
||||
int b[2][2];
|
||||
assert(std::ranges::end(b) == b + 2);
|
||||
assert(std::ranges::cend(b) == b + 2);
|
||||
|
||||
EndMember c[2];
|
||||
assert(std::ranges::end(c) == c + 2);
|
||||
assert(std::ranges::cend(c) == c + 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct EndMemberFunction {
|
||||
int x;
|
||||
constexpr const int *begin() const { return nullptr; }
|
||||
constexpr const int *end() const { return &x; }
|
||||
friend constexpr int *end(EndMemberFunction const&);
|
||||
};
|
||||
|
||||
struct EndMemberReturnsInt {
|
||||
int begin() const;
|
||||
int end() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsInt const&>);
|
||||
|
||||
struct EndMemberReturnsVoidPtr {
|
||||
const void *begin() const;
|
||||
const void *end() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsVoidPtr const&>);
|
||||
|
||||
struct Empty { };
|
||||
struct EmptyEndMember {
|
||||
Empty begin() const;
|
||||
Empty end() const;
|
||||
};
|
||||
struct EmptyPtrEndMember {
|
||||
Empty x;
|
||||
constexpr const Empty *begin() const { return nullptr; }
|
||||
constexpr const Empty *end() const { return &x; }
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EmptyEndMember const&>);
|
||||
|
||||
struct PtrConvertible {
|
||||
operator int*() const;
|
||||
};
|
||||
struct PtrConvertibleEndMember {
|
||||
PtrConvertible begin() const;
|
||||
PtrConvertible end() const;
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, PtrConvertibleEndMember const&>);
|
||||
|
||||
struct NoBeginMember {
|
||||
constexpr const int *end();
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, NoBeginMember const&>);
|
||||
|
||||
struct NonConstEndMember {
|
||||
int x;
|
||||
constexpr int *begin() { return nullptr; }
|
||||
constexpr int *end() { return &x; }
|
||||
};
|
||||
|
||||
static_assert( std::is_invocable_v<RangeEndT, NonConstEndMember &>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, NonConstEndMember const&>);
|
||||
static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember &>);
|
||||
static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember const&>);
|
||||
|
||||
struct EnabledBorrowingEndMember {
|
||||
constexpr int *begin() const { return nullptr; }
|
||||
constexpr int *end() const { return &globalBuff[0]; }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingEndMember> = true;
|
||||
|
||||
constexpr bool testEndMember() {
|
||||
EndMember a;
|
||||
assert(std::ranges::end(a) == &a.x);
|
||||
assert(std::ranges::cend(a) == &a.x);
|
||||
|
||||
NonConstEndMember b;
|
||||
assert(std::ranges::end(b) == &b.x);
|
||||
|
||||
EnabledBorrowingEndMember c;
|
||||
assert(std::ranges::end(std::move(c)) == &globalBuff[0]);
|
||||
|
||||
EndMemberFunction d;
|
||||
assert(std::ranges::end(d) == &d.x);
|
||||
assert(std::ranges::cend(d) == &d.x);
|
||||
|
||||
EmptyPtrEndMember e;
|
||||
assert(std::ranges::end(e) == &e.x);
|
||||
assert(std::ranges::cend(e) == &e.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct EndFunction {
|
||||
int x;
|
||||
friend constexpr const int *begin(EndFunction const&) { return nullptr; }
|
||||
friend constexpr const int *end(EndFunction const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
|
||||
|
||||
static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &>);
|
||||
static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);
|
||||
static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);
|
||||
|
||||
struct EndFunctionWithDataMember {
|
||||
int x;
|
||||
int end;
|
||||
friend constexpr const int *begin(EndFunctionWithDataMember const&) { return nullptr; }
|
||||
friend constexpr const int *end(EndFunctionWithDataMember const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
struct EndFunctionWithPrivateEndMember : private EndMember {
|
||||
int y;
|
||||
friend constexpr const int *begin(EndFunctionWithPrivateEndMember const&) { return nullptr; }
|
||||
friend constexpr const int *end(EndFunctionWithPrivateEndMember const& bf) { return &bf.y; }
|
||||
};
|
||||
|
||||
struct EndFunctionReturnsEmptyPtr {
|
||||
Empty x;
|
||||
friend constexpr const Empty *begin(EndFunctionReturnsEmptyPtr const&) { return nullptr; }
|
||||
friend constexpr const Empty *end(EndFunctionReturnsEmptyPtr const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
struct EndFunctionByValue {
|
||||
friend constexpr int *begin(EndFunctionByValue) { return nullptr; }
|
||||
friend constexpr int *end(EndFunctionByValue) { return &globalBuff[1]; }
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeCEndT, EndFunctionByValue>);
|
||||
|
||||
struct EndFunctionEnabledBorrowing {
|
||||
friend constexpr int *begin(EndFunctionEnabledBorrowing) { return nullptr; }
|
||||
friend constexpr int *end(EndFunctionEnabledBorrowing) { return &globalBuff[2]; }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline constexpr bool std::ranges::enable_borrowed_range<EndFunctionEnabledBorrowing> = true;
|
||||
|
||||
struct EndFunctionReturnsInt {
|
||||
friend constexpr int begin(EndFunctionReturnsInt const&);
|
||||
friend constexpr int end(EndFunctionReturnsInt const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsInt const&>);
|
||||
|
||||
struct EndFunctionReturnsVoidPtr {
|
||||
friend constexpr void *begin(EndFunctionReturnsVoidPtr const&);
|
||||
friend constexpr void *end(EndFunctionReturnsVoidPtr const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsVoidPtr const&>);
|
||||
|
||||
struct EndFunctionReturnsEmpty {
|
||||
friend constexpr Empty begin(EndFunctionReturnsEmpty const&);
|
||||
friend constexpr Empty end(EndFunctionReturnsEmpty const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsEmpty const&>);
|
||||
|
||||
struct EndFunctionReturnsPtrConvertible {
|
||||
friend constexpr PtrConvertible begin(EndFunctionReturnsPtrConvertible const&);
|
||||
friend constexpr PtrConvertible end(EndFunctionReturnsPtrConvertible const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsPtrConvertible const&>);
|
||||
|
||||
struct NoBeginFunction {
|
||||
friend constexpr const int *end(NoBeginFunction const&);
|
||||
};
|
||||
|
||||
static_assert(!std::is_invocable_v<RangeEndT, NoBeginFunction const&>);
|
||||
|
||||
struct BeginMemberEndFunction {
|
||||
int x;
|
||||
constexpr const int *begin() const { return nullptr; }
|
||||
friend constexpr const int *end(BeginMemberEndFunction const& bf) { return &bf.x; }
|
||||
};
|
||||
|
||||
constexpr bool testEndFunction() {
|
||||
const EndFunction a{};
|
||||
assert(std::ranges::end(a) == &a.x);
|
||||
EndFunction aa{};
|
||||
assert(std::ranges::cend(aa) == &aa.x);
|
||||
|
||||
EndFunctionByValue b;
|
||||
assert(std::ranges::end(b) == &globalBuff[1]);
|
||||
assert(std::ranges::cend(b) == &globalBuff[1]);
|
||||
|
||||
EndFunctionEnabledBorrowing c;
|
||||
assert(std::ranges::end(std::move(c)) == &globalBuff[2]);
|
||||
|
||||
const EndFunctionReturnsEmptyPtr d{};
|
||||
assert(std::ranges::end(d) == &d.x);
|
||||
EndFunctionReturnsEmptyPtr dd{};
|
||||
assert(std::ranges::cend(dd) == &dd.x);
|
||||
|
||||
const EndFunctionWithDataMember e{};
|
||||
assert(std::ranges::end(e) == &e.x);
|
||||
EndFunctionWithDataMember ee{};
|
||||
assert(std::ranges::cend(ee) == &ee.x);
|
||||
|
||||
const EndFunctionWithPrivateEndMember f{};
|
||||
assert(std::ranges::end(f) == &f.y);
|
||||
EndFunctionWithPrivateEndMember ff{};
|
||||
assert(std::ranges::cend(ff) == &ff.y);
|
||||
|
||||
const BeginMemberEndFunction g{};
|
||||
assert(std::ranges::end(g) == &g.x);
|
||||
BeginMemberEndFunction gg{};
|
||||
assert(std::ranges::cend(gg) == &gg.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct NoThrowMemberEnd {
|
||||
T begin() noexcept;
|
||||
T begin() const noexcept;
|
||||
T end() noexcept;
|
||||
T end() const noexcept;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct NoThrowADLEnd {
|
||||
friend T begin(NoThrowADLEnd&) noexcept;
|
||||
friend T begin(NoThrowADLEnd const&) noexcept;
|
||||
friend T end(NoThrowADLEnd&) noexcept;
|
||||
friend T end(NoThrowADLEnd const&) noexcept;
|
||||
};
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<int (&)[10]>()));
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberEnd<int*>&>()));
|
||||
ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberEnd<ThrowingIterator<int> >&>()));
|
||||
ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLEnd<int*>&>()));
|
||||
ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLEnd<ThrowingIterator<int> >&>()));
|
||||
|
||||
int main(int, char**) {
|
||||
testArray();
|
||||
static_assert(testArray());
|
||||
|
||||
testEndMember();
|
||||
static_assert(testEndMember());
|
||||
|
||||
testEndFunction();
|
||||
static_assert(testEndFunction());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// unspecified begin;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
using end_t = decltype(std::ranges::end);
|
||||
|
||||
// clang-format off
|
||||
template <class T>
|
||||
requires(!std::invocable<end_t&, T>)
|
||||
void f() {}
|
||||
// clang-format on
|
||||
|
||||
void test() {
|
||||
struct incomplete;
|
||||
f<incomplete(&)[]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
f<incomplete(&)[10]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-3 {{no matching function for call to 'f'}}
|
||||
f<incomplete(&)[2][2]>();
|
||||
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
|
||||
// expected-error@-2 {{no matching function for call to 'f'}}
|
||||
|
||||
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
|
||||
f<incomplete(&&)[10]>();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// template<class T>
|
||||
// using iterator_t = decltype(ranges::begin(declval<T&>()));
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#include "test_range.h"
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<test_range<input_iterator> >, input_iterator<int*> >);
|
||||
static_assert(std::same_as<stdr::iterator_t<test_range<input_iterator> const>, input_iterator<int const*> >);
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<test_non_const_range<input_iterator> >, input_iterator<int*> >);
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<test_common_range<input_iterator> >, input_iterator<int*> >);
|
||||
static_assert(std::same_as<stdr::iterator_t<test_common_range<input_iterator> const>, input_iterator<int const*> >);
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<test_non_const_common_range<input_iterator> >, input_iterator<int*> >);
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// match_results
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<std::cmatch>, std::cmatch::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<std::cmatch const>, std::cmatch::const_iterator>);
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// string
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<std::string>, std::string::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<std::string const>, std::string::const_iterator>);
|
|
@ -0,0 +1,24 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
// XFAIL: msvc && clang
|
||||
|
||||
// string_view
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
|
||||
namespace stdr = std::ranges;
|
||||
|
||||
static_assert(std::same_as<stdr::iterator_t<std::string_view>, std::string_view::iterator>);
|
||||
static_assert(std::same_as<stdr::iterator_t<std::string_view const>, std::string_view::const_iterator>);
|
|
@ -0,0 +1,59 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 LIBCXX_TEST_SUPPORT_TEST_RANGE_H
|
||||
#define LIBCXX_TEST_SUPPORT_TEST_RANGE_H
|
||||
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
#ifdef _LIBCPP_HAS_NO_RANGES
|
||||
#error "test/suppoort/test_range.h" can only be included in builds supporting ranges
|
||||
#endif
|
||||
|
||||
struct sentinel {
|
||||
bool operator==(std::input_or_output_iterator auto) const;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
template <template <class...> class I>
|
||||
requires std::input_or_output_iterator<I<int*> >
|
||||
struct test_range {
|
||||
I<int*> begin();
|
||||
I<int const*> begin() const;
|
||||
sentinel end();
|
||||
sentinel end() const;
|
||||
};
|
||||
|
||||
template <template <class...> class I>
|
||||
requires std::input_or_output_iterator<I<int*> >
|
||||
struct test_non_const_range {
|
||||
I<int*> begin();
|
||||
sentinel end();
|
||||
};
|
||||
|
||||
template <template <class...> class I>
|
||||
requires std::input_or_output_iterator<I<int*> >
|
||||
struct test_common_range {
|
||||
I<int*> begin();
|
||||
I<int const*> begin() const;
|
||||
I<int*> end();
|
||||
I<int*> end() const;
|
||||
};
|
||||
|
||||
template <template <class...> class I>
|
||||
requires std::input_or_output_iterator<I<int*> >
|
||||
struct test_non_const_common_range {
|
||||
I<int*> begin();
|
||||
I<int*> end();
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // LIBCXX_TEST_SUPPORT_TEST_RANGE_H
|
Loading…
Reference in New Issue