mirror of
https://github.com/intel/llvm.git
synced 2026-01-23 07:58:23 +08:00
[libc++][ranges] P2711R1 Making multi-param constructors of views explicit
Implemented [[ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2711r1.html | P2711R1 ]] for existing views. (`join_with_view` is not yet implemented) Reviewed By: #libc, philnik Differential Revision: https://reviews.llvm.org/D144822
This commit is contained in:
@@ -43,6 +43,7 @@ Paper Status
|
||||
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
|
||||
clang doesn't issue a diagnostic for deprecated using template declarations.
|
||||
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
|
||||
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
|
||||
|
||||
.. _issues-status-cxx2b:
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
"`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|"
|
||||
"`P2770R0 <https://wg21.link/P2770R0>`__","LWG", "Stashing stashing ``iterators`` for proper flattening","February 2023","","","|ranges|"
|
||||
"`P2164R9 <https://wg21.link/P2164R9>`__","LWG", "``views::enumerate``","February 2023","","","|ranges|"
|
||||
"`P2711R1 <https://wg21.link/P2711R1>`__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","","","|ranges|"
|
||||
"`P2711R1 <https://wg21.link/P2711R1>`__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","|Partial| [#note-P2711R1]_","","|ranges|"
|
||||
"`P2609R3 <https://wg21.link/P2609R3>`__","LWG", "Relaxing Ranges Just A Smidge","February 2023","","","|ranges|"
|
||||
"`P2713R1 <https://wg21.link/P2713R1>`__","LWG", "Escaping improvements in ``std::format``","February 2023","","","|format|"
|
||||
"`P2675R1 <https://wg21.link/P2675R1>`__","LWG", "``format``'s width estimation is too approximate and not forward compatible","February 2023","","","|format|"
|
||||
|
||||
|
@@ -847,6 +847,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
|
||||
# define _LIBCPP_EXPLICIT_SINCE_CXX14 explicit
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_STD_VER >= 23
|
||||
# define _LIBCPP_EXPLICIT_SINCE_CXX23 explicit
|
||||
# else
|
||||
# define _LIBCPP_EXPLICIT_SINCE_CXX23
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_STD_VER >= 14
|
||||
# define _LIBCPP_CONSTEXPR_SINCE_CXX14 constexpr
|
||||
# else
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
drop_view() requires default_initializable<_View> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr drop_view(_View __base, range_difference_t<_View> __count)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_view(_View __base, range_difference_t<_View> __count)
|
||||
: __count_(__count)
|
||||
, __base_(std::move(__base))
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
requires default_initializable<_View> && default_initializable<_Pred>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr drop_while_view(_View __base, _Pred __pred)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_while_view(_View __base, _Pred __pred)
|
||||
: __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
|
||||
|
||||
@@ -64,10 +64,8 @@ namespace ranges {
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
filter_view() requires default_initializable<_View> && default_initializable<_Pred> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr filter_view(_View __base, _Pred __pred)
|
||||
: __base_(std::move(__base)), __pred_(in_place, std::move(__pred))
|
||||
{ }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 filter_view(_View __base, _Pred __pred)
|
||||
: __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) {}
|
||||
|
||||
template<class _Vp = _View>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
|
||||
@@ -314,7 +314,7 @@ namespace ranges {
|
||||
constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) { }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)
|
||||
: __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) {
|
||||
// Validate the precondition if possible.
|
||||
if constexpr (totally_ordered_with<_Start, _BoundSentinel>) {
|
||||
@@ -324,17 +324,17 @@ namespace ranges {
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr iota_view(__iterator __first, __iterator __last)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last)
|
||||
requires same_as<_Start, _BoundSentinel>
|
||||
: iota_view(std::move(__first.__value_), std::move(__last.__value_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr iota_view(__iterator __first, _BoundSentinel __last)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last)
|
||||
requires same_as<_BoundSentinel, unreachable_sentinel_t>
|
||||
: iota_view(std::move(__first.__value_), std::move(__last)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr iota_view(__iterator __first, __sentinel __last)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last)
|
||||
requires(!same_as<_Start, _BoundSentinel> && !same_as<_Start, unreachable_sentinel_t>)
|
||||
: iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {}
|
||||
|
||||
|
||||
@@ -82,14 +82,14 @@ public:
|
||||
requires default_initializable<_View> && default_initializable<_Pattern> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr lazy_split_view(_View __base, _Pattern __pattern)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_View __base, _Pattern __pattern)
|
||||
: __base_(std::move(__base)), __pattern_(std::move(__pattern)) {}
|
||||
|
||||
template <input_range _Range>
|
||||
requires constructible_from<_View, views::all_t<_Range>> &&
|
||||
constructible_from<_Pattern, single_view<range_value_t<_Range>>>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
|
||||
: __base_(views::all(std::forward<_Range>(__r)))
|
||||
, __pattern_(views::single(std::move(__e))) {}
|
||||
|
||||
|
||||
@@ -75,13 +75,14 @@ public:
|
||||
requires default_initializable<_View> && default_initializable<_Pattern>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 split_view(_View __base, _Pattern __pattern)
|
||||
: __base_(std::move(__base)), __pattern_(std::move((__pattern))) {}
|
||||
|
||||
template <forward_range _Range>
|
||||
requires constructible_from<_View, views::all_t<_Range>> &&
|
||||
constructible_from<_Pattern, single_view<range_value_t<_Range>>>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
|
||||
split_view(_Range&& __range, range_value_t<_Range> __elem)
|
||||
: __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
|
||||
|
||||
@@ -67,7 +67,8 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
take_view() requires default_initializable<_View> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_view(_View __base, range_difference_t<_View> __count)
|
||||
: __base_(std::move(__base)), __count_(__count) {
|
||||
_LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero");
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
requires default_initializable<_View> && default_initializable<_Pred>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr take_while_view(_View __base, _Pred __pred)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred)
|
||||
: __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
requires default_initializable<_View> && default_initializable<_Fn> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr transform_view(_View __base, _Fn __func)
|
||||
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 transform_view(_View __base, _Fn __func)
|
||||
: __func_(std::in_place, std::move(__func)), __base_(std::move(__base)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr drop_while_view(V base, Pred pred);
|
||||
// constexpr drop_while_view(V base, Pred pred); // explicit since C++23
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct View : std::ranges::view_base {
|
||||
MoveOnly mo;
|
||||
@@ -32,9 +34,23 @@ struct Pred {
|
||||
bool operator()(int) const;
|
||||
};
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::drop_while_view<View, Pred>, View, Pred>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::drop_while_view<View, Pred>, View, Pred>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
std::ranges::drop_while_view<View, Pred> dwv = {View{{}, MoveOnly{5}}, Pred{}};
|
||||
std::ranges::drop_while_view<View, Pred> dwv{View{{}, MoveOnly{5}}, Pred{}};
|
||||
assert(dwv.pred().moved);
|
||||
assert(!dwv.pred().copied);
|
||||
assert(std::move(dwv).base().mo.get() == 5);
|
||||
@@ -45,5 +61,6 @@ constexpr bool test() {
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,28 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr drop_view(V base, range_difference_t<V> count);
|
||||
// constexpr drop_view(V base, range_difference_t<V> count); // explicit since C++23
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::drop_view<View>, View, std::ranges::range_difference_t<View>>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert(test_convertible<std::ranges::drop_view<View>, View, std::ranges::range_difference_t<View>>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
std::ranges::drop_view dropView1(MoveOnlyView(), 4);
|
||||
assert(dropView1.size() == 4);
|
||||
|
||||
@@ -94,4 +94,15 @@ struct CountedView : std::ranges::view_base {
|
||||
constexpr CountedIter end() const { return CountedIter(ForwardIter(globalBuff + 8)); }
|
||||
};
|
||||
|
||||
struct View : std::ranges::view_base {
|
||||
constexpr explicit View(int* b, int* e) : begin_(b), end_(e) { }
|
||||
|
||||
constexpr int* begin() const { return begin_; }
|
||||
constexpr int* end() const { return end_; }
|
||||
|
||||
private:
|
||||
int* begin_;
|
||||
int* end_;
|
||||
};
|
||||
|
||||
#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_DROP_TYPES_H
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr filter_view(View, Pred);
|
||||
|
||||
#include <ranges>
|
||||
// constexpr filter_view(View, Pred); // explicit since C++23
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
struct Range : std::ranges::view_base {
|
||||
@@ -41,6 +43,20 @@ struct TrackingRange : TrackInitialization, std::ranges::view_base {
|
||||
int* end() const;
|
||||
};
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::filter_view<Range, Pred>, Range, Pred>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::filter_view<Range, Pred>, Range, Pred>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
@@ -57,19 +73,6 @@ constexpr bool test() {
|
||||
assert(it == end);
|
||||
}
|
||||
|
||||
// Test implicit syntax
|
||||
{
|
||||
Range range(buff, buff + 8);
|
||||
Pred pred;
|
||||
std::ranges::filter_view<Range, Pred> view = {range, pred};
|
||||
auto it = view.begin(), end = view.end();
|
||||
assert(*it++ == 1);
|
||||
assert(*it++ == 3);
|
||||
assert(*it++ == 5);
|
||||
assert(*it++ == 7);
|
||||
assert(it == end);
|
||||
}
|
||||
|
||||
// Make sure we move the view
|
||||
{
|
||||
bool moved = false, copied = false;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// template <input_range Range>
|
||||
// requires constructible_from<View, views::all_t<Range>> &&
|
||||
// constructible_from<Pattern, single_view<range_value_t<Range>>>
|
||||
// constexpr lazy_split_view(Range&& r, range_value_t<Range> e);
|
||||
// constexpr lazy_split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
|
||||
|
||||
#include <ranges>
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "types.h"
|
||||
|
||||
struct ElementWithCounting {
|
||||
@@ -88,6 +90,22 @@ static_assert( std::ranges::random_access_range<StrView>);
|
||||
static_assert( std::ranges::view<StrView>);
|
||||
static_assert( std::is_copy_constructible_v<StrView>);
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(
|
||||
!test_convertible<std::ranges::lazy_split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert(
|
||||
test_convertible<std::ranges::lazy_split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
using V = std::ranges::lazy_split_view<StrView, StrView>;
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr lazy_split_view(View base, Pattern pattern);
|
||||
|
||||
#include <ranges>
|
||||
// constexpr lazy_split_view(View base, Pattern pattern); // explicit since C++23
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "types.h"
|
||||
|
||||
struct ViewWithCounting : std::ranges::view_base {
|
||||
@@ -41,9 +42,27 @@ struct ViewWithCounting : std::ranges::view_base {
|
||||
constexpr ViewWithCounting& operator=(ViewWithCounting&&) = default;
|
||||
constexpr bool operator==(const ViewWithCounting&) const { return true; }
|
||||
};
|
||||
|
||||
static_assert(std::ranges::forward_range<ViewWithCounting>);
|
||||
static_assert(std::ranges::view<ViewWithCounting>);
|
||||
|
||||
using View = ViewWithCounting;
|
||||
using Pattern = ViewWithCounting;
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::lazy_split_view<View, Pattern>, View, Pattern>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::lazy_split_view<View, Pattern>, View, Pattern>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
// Calling the constructor with `(ForwardView, ForwardView)`.
|
||||
{
|
||||
@@ -62,9 +81,6 @@ constexpr bool test() {
|
||||
|
||||
// Make sure the arguments are moved, not copied.
|
||||
{
|
||||
using View = ViewWithCounting;
|
||||
using Pattern = ViewWithCounting;
|
||||
|
||||
// Arguments are lvalues.
|
||||
{
|
||||
int view_copied = 0, view_moved = 0, pattern_copied = 0, pattern_moved = 0;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// template <input_range Range>
|
||||
// requires constructible_from<View, views::all_t<Range>> &&
|
||||
// constructible_from<Pattern, single_view<range_value_t<Range>>>
|
||||
// constexpr split_view(Range&& r, range_value_t<Range> e);
|
||||
// constexpr split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Counting {
|
||||
int* times_copied = nullptr;
|
||||
int* times_moved = nullptr;
|
||||
@@ -68,6 +71,22 @@ static_assert(std::ranges::random_access_range<StrView>);
|
||||
static_assert(std::ranges::view<StrView>);
|
||||
static_assert(std::is_copy_constructible_v<StrView>);
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(
|
||||
!test_convertible<std::ranges::split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
# else
|
||||
|
||||
static_assert(
|
||||
test_convertible<std::ranges::split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
using V = std::ranges::split_view<StrView, StrView>;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr split_view(View base, Pattern pattern);
|
||||
// constexpr split_view(View base, Pattern pattern); // explicit since C++23
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -16,6 +16,9 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct ViewWithCounting : std::ranges::view_base {
|
||||
int* times_copied = nullptr;
|
||||
int* times_moved = nullptr;
|
||||
@@ -38,6 +41,23 @@ struct ViewWithCounting : std::ranges::view_base {
|
||||
constexpr bool operator==(const ViewWithCounting&) const { return true; }
|
||||
};
|
||||
|
||||
using View = ViewWithCounting;
|
||||
using Pattern = ViewWithCounting;
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
std::string_view input = "abc def";
|
||||
@@ -48,9 +68,6 @@ constexpr bool test() {
|
||||
|
||||
// Make sure the arguments are moved, not copied.
|
||||
{
|
||||
using View = ViewWithCounting;
|
||||
using Pattern = ViewWithCounting;
|
||||
|
||||
// Arguments are lvalues.
|
||||
{
|
||||
int view_copied = 0, view_moved = 0, pattern_copied = 0, pattern_moved = 0;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr take_while_view(V base, Pred pred);
|
||||
// constexpr take_while_view(V base, Pred pred); // explicit since C++23
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct View : std::ranges::view_base {
|
||||
MoveOnly mo;
|
||||
@@ -32,9 +34,23 @@ struct Pred {
|
||||
bool operator()(int) const;
|
||||
};
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::take_while_view<View, Pred>, View, Pred>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert(test_convertible<std::ranges::take_while_view<View, Pred>, View, Pred>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
std::ranges::take_while_view<View, Pred> twv = {View{{}, MoveOnly{5}}, Pred{}};
|
||||
std::ranges::take_while_view<View, Pred> twv{View{{}, MoveOnly{5}}, Pred{}};
|
||||
assert(twv.pred().moved);
|
||||
assert(!twv.pred().copied);
|
||||
assert(std::move(twv).base().mo.get() == 5);
|
||||
@@ -45,5 +61,6 @@ constexpr bool test() {
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,31 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr take_view(V base, range_difference_t<V> count);
|
||||
// constexpr take_view(V base, range_difference_t<V> count); // explicit since C++23
|
||||
|
||||
#include <ranges>
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_convertible.h"
|
||||
#include "test_iterators.h"
|
||||
#include "test_macros.h"
|
||||
#include "test_range.h"
|
||||
#include "types.h"
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::take_view<View>, View, std::ranges::range_difference_t<View>>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert(test_convertible<std::ranges::take_view<View>, View, std::ranges::range_difference_t<View>>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
|
||||
@@ -54,4 +54,15 @@ static_assert(std::ranges::view<SizedRandomAccessView>);
|
||||
static_assert(std::ranges::random_access_range<SizedRandomAccessView>);
|
||||
static_assert(std::ranges::sized_range<SizedRandomAccessView>);
|
||||
|
||||
struct View : std::ranges::view_base {
|
||||
constexpr explicit View(int* b, int* e) : begin_(b), end_(e) { }
|
||||
|
||||
constexpr int* begin() const { return begin_; }
|
||||
constexpr int* end() const { return end_; }
|
||||
|
||||
private:
|
||||
int* begin_;
|
||||
int* end_;
|
||||
};
|
||||
|
||||
#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_TAKE_TYPES_H
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr transform_view(View, F);
|
||||
|
||||
#include <ranges>
|
||||
// constexpr transform_view(View, F); // explicit since C++23
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Range : std::ranges::view_base {
|
||||
constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) { }
|
||||
constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}
|
||||
constexpr int* begin() const { return begin_; }
|
||||
constexpr int* end() const { return end_; }
|
||||
|
||||
@@ -28,6 +30,20 @@ struct F {
|
||||
constexpr int operator()(int i) const { return i + 100; }
|
||||
};
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::transform_view<Range, F>, Range, F>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::transform_view<Range, F>, Range, F>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
@@ -41,16 +57,6 @@ constexpr bool test() {
|
||||
assert(view[7] == 108);
|
||||
}
|
||||
|
||||
{
|
||||
Range range(buff, buff + 8);
|
||||
F f;
|
||||
std::ranges::transform_view<Range, F> view = {range, f};
|
||||
assert(view[0] == 101);
|
||||
assert(view[1] == 102);
|
||||
// ...
|
||||
assert(view[7] == 108);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,55 @@
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// constexpr iota_view(iterator first, see below last);
|
||||
// constexpr iota_view(iterator first, see below last); // explicit since C++23
|
||||
|
||||
#include <ranges>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
std::ranges::iota_view<SomeInt, SomeInt> view;
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt>,
|
||||
decltype(std::ranges::iota_view{SomeInt{0}}.begin()),
|
||||
decltype(std::unreachable_sentinel)>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert(test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
static_assert(test_convertible<std::ranges::iota_view<SomeInt>,
|
||||
decltype(std::ranges::iota_view{SomeInt{0}}.begin()),
|
||||
decltype(std::unreachable_sentinel)>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
static_assert(test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
std::ranges::iota_view commonView(SomeInt(0), SomeInt(10));
|
||||
|
||||
@@ -14,13 +14,52 @@ TEST_CLANG_DIAGNOSTIC_IGNORED("-Wsign-compare")
|
||||
TEST_GCC_DIAGNOSTIC_IGNORED("-Wsign-compare")
|
||||
TEST_MSVC_DIAGNOSTIC_IGNORED(4018 4389) // various "signed/unsigned mismatch"
|
||||
|
||||
// constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
|
||||
// constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); // explicit since C++23
|
||||
|
||||
#include <ranges>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "types.h"
|
||||
|
||||
// SFINAE tests.
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt>{}.begin()),
|
||||
decltype(std::unreachable_sentinel)>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
static_assert(!test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
#else
|
||||
|
||||
static_assert( test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
|
||||
decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
static_assert( test_convertible<std::ranges::iota_view<SomeInt>,
|
||||
decltype(std::ranges::iota_view<SomeInt>{}.begin()),
|
||||
decltype(std::unreachable_sentinel)>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
static_assert( test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
|
||||
decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
|
||||
"This constructor must not be explicit");
|
||||
|
||||
#endif // TEST_STD_VER >= 23
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(0), SomeInt(10));
|
||||
|
||||
Reference in New Issue
Block a user