diff --git a/libcxx/docs/Status/Cxx2b.rst b/libcxx/docs/Status/Cxx2b.rst --- a/libcxx/docs/Status/Cxx2b.rst +++ b/libcxx/docs/Status/Cxx2b.rst @@ -43,6 +43,7 @@ .. [#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: diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -108,7 +108,7 @@ "`P0290R4 `__","LWG", "``apply()`` for ``synchronized_value``","February 2023","","","|concurrency TS|" "`P2770R0 `__","LWG", "Stashing stashing ``iterators`` for proper flattening","February 2023","","","|ranges|" "`P2164R9 `__","LWG", "``views::enumerate``","February 2023","","","|ranges|" -"`P2711R1 `__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","","","|ranges|" +"`P2711R1 `__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","|Partial| [#note-P2711R1]_","","|ranges|" "`P2609R3 `__","LWG", "Relaxing Ranges Just A Smidge","February 2023","","","|ranges|" "`P2713R1 `__","LWG", "Escaping improvements in ``std::format``","February 2023","","","|format|" "`P2675R1 `__","LWG", "``format``'s width estimation is too approximate and not forward compatible","February 2023","","","|format|" diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -847,6 +847,12 @@ # 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 diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -74,7 +74,7 @@ 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)) { diff --git a/libcxx/include/__ranges/drop_while_view.h b/libcxx/include/__ranges/drop_while_view.h --- a/libcxx/include/__ranges/drop_while_view.h +++ b/libcxx/include/__ranges/drop_while_view.h @@ -51,7 +51,7 @@ 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& diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h --- a/libcxx/include/__ranges/filter_view.h +++ b/libcxx/include/__ranges/filter_view.h @@ -64,10 +64,8 @@ _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 _LIBCPP_HIDE_FROM_ABI diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -314,7 +314,7 @@ 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 @@ } _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_)) {} diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h --- a/libcxx/include/__ranges/lazy_split_view.h +++ b/libcxx/include/__ranges/lazy_split_view.h @@ -82,14 +82,14 @@ 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 requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view>> _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))) {} diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h --- a/libcxx/include/__ranges/split_view.h +++ b/libcxx/include/__ranges/split_view.h @@ -75,13 +75,14 @@ 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 requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view>> - _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& diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -67,7 +67,8 @@ _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"); } diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h --- a/libcxx/include/__ranges/take_while_view.h +++ b/libcxx/include/__ranges/take_while_view.h @@ -67,7 +67,7 @@ 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& diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -71,7 +71,7 @@ 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 diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp @@ -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 #include @@ -16,6 +16,8 @@ #include #include "MoveOnly.h" +#include "test_convertible.h" +#include "test_macros.h" struct View : std::ranges::view_base { MoveOnly mo; @@ -32,9 +34,23 @@ bool operator()(int) const; }; +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, View, Pred>(), + "This constructor must be explicit"); + +#else + +static_assert( test_convertible, View, Pred>(), + "This constructor must not be explicit"); + +#endif // TEST_STD_VER >= 23 + constexpr bool test() { { - std::ranges::drop_while_view dwv = {View{{}, MoveOnly{5}}, Pred{}}; + std::ranges::drop_while_view 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 @@ int main(int, char**) { test(); static_assert(test()); + return 0; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp @@ -8,13 +8,28 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// constexpr drop_view(V base, range_difference_t count); +// constexpr drop_view(V base, range_difference_t count); // explicit since C++23 #include +#include "test_convertible.h" #include "test_macros.h" #include "types.h" +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, View, std::ranges::range_difference_t>(), + "This constructor must be explicit"); + +#else + +static_assert(test_convertible, View, std::ranges::range_difference_t>(), + "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); diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.drop/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/types.h @@ -94,4 +94,15 @@ 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 diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp @@ -8,12 +8,14 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// constexpr filter_view(View, Pred); - -#include +// constexpr filter_view(View, Pred); // explicit since C++23 #include +#include #include + +#include "test_convertible.h" +#include "test_macros.h" #include "types.h" struct Range : std::ranges::view_base { @@ -41,6 +43,20 @@ int* end() const; }; +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, Range, Pred>(), + "This constructor must be explicit"); + +#else + +static_assert( test_convertible, 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 @@ assert(it == end); } - // Test implicit syntax - { - Range range(buff, buff + 8); - Pred pred; - std::ranges::filter_view 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; diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp @@ -11,7 +11,7 @@ // template // requires constructible_from> && // constructible_from>> -// constexpr lazy_split_view(Range&& r, range_value_t e); +// constexpr lazy_split_view(Range&& r, range_value_t e); // explicit since C++23 #include @@ -20,6 +20,8 @@ #include #include #include + +#include "test_convertible.h" #include "types.h" struct ElementWithCounting { @@ -88,6 +90,22 @@ static_assert( std::ranges::view); static_assert( std::is_copy_constructible_v); +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert( + !test_convertible, StrView, std::ranges::range_value_t>(), + "This constructor must be explicit"); + +#else + +static_assert( + test_convertible, StrView, std::ranges::range_value_t>(), + "This constructor must not be explicit"); + +#endif // TEST_STD_VER >= 23 + constexpr bool test() { { using V = std::ranges::lazy_split_view; diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp @@ -8,13 +8,14 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// constexpr lazy_split_view(View base, Pattern pattern); - -#include +// constexpr lazy_split_view(View base, Pattern pattern); // explicit since C++23 #include +#include #include #include + +#include "test_convertible.h" #include "types.h" struct ViewWithCounting : std::ranges::view_base { @@ -41,9 +42,27 @@ constexpr ViewWithCounting& operator=(ViewWithCounting&&) = default; constexpr bool operator==(const ViewWithCounting&) const { return true; } }; + static_assert(std::ranges::forward_range); static_assert(std::ranges::view); +using View = ViewWithCounting; +using Pattern = ViewWithCounting; + +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, View, Pattern>(), + "This constructor must be explicit"); + +#else + +static_assert( test_convertible, 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 @@ // 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; diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp @@ -11,7 +11,7 @@ // template // requires constructible_from> && // constructible_from>> -// constexpr split_view(Range&& r, range_value_t e); +// constexpr split_view(Range&& r, range_value_t e); // explicit since C++23 #include #include @@ -21,6 +21,9 @@ #include #include +#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::view); static_assert(std::is_copy_constructible_v); +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert( + !test_convertible, StrView, std::ranges::range_value_t>(), + "This constructor must be explicit"); + +# else + +static_assert( + test_convertible, StrView, std::ranges::range_value_t>(), + "This constructor must not be explicit"); + +#endif // TEST_STD_VER >= 23 + constexpr bool test() { { using V = std::ranges::split_view; diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp @@ -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 #include @@ -16,6 +16,9 @@ #include #include +#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 @@ 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, View, Pattern>(), + "This constructor must be explicit"); + +#else + +static_assert( test_convertible, 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 @@ // 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; diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp @@ -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 #include @@ -16,6 +16,8 @@ #include #include "MoveOnly.h" +#include "test_convertible.h" +#include "test_macros.h" struct View : std::ranges::view_base { MoveOnly mo; @@ -32,9 +34,23 @@ bool operator()(int) const; }; +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, View, Pred>(), + "This constructor must be explicit"); + +#else + +static_assert(test_convertible, View, Pred>(), + "This constructor must not be explicit"); + +#endif // TEST_STD_VER >= 23 + constexpr bool test() { { - std::ranges::take_while_view twv = {View{{}, MoveOnly{5}}, Pred{}}; + std::ranges::take_while_view 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 @@ int main(int, char**) { test(); static_assert(test()); + return 0; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp @@ -8,16 +8,31 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// constexpr take_view(V base, range_difference_t count); +// constexpr take_view(V base, range_difference_t count); // explicit since C++23 -#include #include +#include -#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, View, std::ranges::range_difference_t>(), + "This constructor must be explicit"); + +#else + +static_assert(test_convertible, View, std::ranges::range_difference_t>(), + "This constructor must be explicit"); + +#endif // TEST_STD_VER >= 23 + constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/types.h b/libcxx/test/std/ranges/range.adaptors/range.take/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.take/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.take/types.h @@ -54,4 +54,15 @@ static_assert(std::ranges::random_access_range); static_assert(std::ranges::sized_range); +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 diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp @@ -8,14 +8,16 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -// constexpr transform_view(View, F); +// constexpr transform_view(View, F); // explicit since C++23 +#include #include -#include +#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 @@ constexpr int operator()(int i) const { return i + 100; } }; +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, Range, F>(), + "This constructor must be explicit"); + +#else + +static_assert( test_convertible, 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 @@ assert(view[7] == 108); } - { - Range range(buff, buff + 8); - F f; - std::ranges::transform_view view = {range, f}; - assert(view[0] == 101); - assert(view[1] == 102); - // ... - assert(view[7] == 108); - } - return true; } diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp --- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp @@ -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 #include +#include "test_convertible.h" #include "test_macros.h" #include "types.h" +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +std::ranges::iota_view view; + +static_assert(!test_convertible, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::ranges::iota_view{}.end())>(), + "This constructor must be explicit"); + +static_assert(!test_convertible, + decltype(std::ranges::iota_view{SomeInt{0}}.begin()), + decltype(std::unreachable_sentinel)>(), + "This constructor must be explicit"); + +static_assert(!test_convertible>, + 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, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::ranges::iota_view{}.end())>(), + "This constructor must not be explicit"); + +static_assert(test_convertible, + decltype(std::ranges::iota_view{SomeInt{0}}.begin()), + decltype(std::unreachable_sentinel)>(), + "This constructor must not be explicit"); + +static_assert(test_convertible>, + 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)); diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp --- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp @@ -14,13 +14,52 @@ TEST_GCC_DIAGNOSTIC_IGNORED("-Wsign-compare") TEST_MSVC_DIAGNOSTIC_IGNORED(4018 4389) // various "signed/unsigned mismatch" -// constexpr iota_view(type_identity_t value, type_identity_t bound); +// constexpr iota_view(type_identity_t value, type_identity_t bound); // explicit since C++23 #include #include +#include "test_convertible.h" #include "types.h" +// SFINAE tests. + +#if TEST_STD_VER >= 23 + +static_assert(!test_convertible, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::ranges::iota_view{}.end())>(), + "This constructor must be explicit"); + +static_assert(!test_convertible, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::unreachable_sentinel)>(), + "This constructor must be explicit"); + +static_assert(!test_convertible>, + 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, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::ranges::iota_view{}.end())>(), + "This constructor must not be explicit"); + +static_assert( test_convertible, + decltype(std::ranges::iota_view{}.begin()), + decltype(std::unreachable_sentinel)>(), + "This constructor must not be explicit"); + +static_assert( test_convertible>, + 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 io(SomeInt(0), SomeInt(10));