[libcxx-commits] [libcxx] 481ad59 - [libcxx][ranges] Add `std::ranges::single_view`.
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jul 30 10:53:37 PDT 2021
Author: zoecarver
Date: 2021-07-30T10:53:20-07:00
New Revision: 481ad59b9fa467882873dd7e45645e613cb77786
URL: https://github.com/llvm/llvm-project/commit/481ad59b9fa467882873dd7e45645e613cb77786
DIFF: https://github.com/llvm/llvm-project/commit/481ad59b9fa467882873dd7e45645e613cb77786.diff
LOG: [libcxx][ranges] Add `std::ranges::single_view`.
Differential Revision: https://reviews.llvm.org/D106840
Added:
libcxx/include/__ranges/single_view.h
libcxx/test/libcxx/diagnostics/detail.headers/ranges/single_view.module.verify.cpp
libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/assign.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/begin.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/ctad.compile.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/ctor.default.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/ctor.in_place.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/ctor.value.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/data.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/end.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/range_concept_conformance.compile.pass.cpp
libcxx/test/std/ranges/range.factories/range.single.view/size.pass.cpp
Modified:
libcxx/docs/Status/RangesPaper.csv
libcxx/include/CMakeLists.txt
libcxx/include/__ranges/copyable_box.h
libcxx/include/module.modulemap
libcxx/include/ranges
libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index aede9e6fafd54..d0e7f5c88fa09 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -142,7 +142,7 @@ Section,Description,Dependencies,Assignee,Complete
`[range.take] <http://wg21.link/range.take>`_,take_view,[range.all],Zoe Carver,✅
`[range.join] <http://wg21.link/range.join>`_,join_view,[range.all],Christopher Di Bella,Not started
`[range.empty] <http://wg21.link/range.empty>`_,`empty_view <https://llvm.org/D103208>`_,[view.interface],Zoe Carver,✅
-`[range.single] <http://wg21.link/range.single>`_,single_view,[view.interface],Zoe Carver,In Progress
+`[range.single] <http://wg21.link/range.single>`_,single_view,[view.interface],Zoe Carver,✅
`[range.split] <http://wg21.link/range.split>`_,split_view,[range.all],Unassigned,Not started
`[range.counted] <http://wg21.link/range.counted>`_,view::counted,[range.subrange],Zoe Carver,Not started
`[range.common] <http://wg21.link/range.common>`_,common_view,[range.all],Zoe Carver,✅
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 68ac54621d1e9..1be2df1b5c381 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -199,9 +199,10 @@ set(files
__ranges/enable_view.h
__ranges/non_propagating_cache.h
__ranges/ref_view.h
- __ranges/take_view.h
+ __ranges/single_view.h
__ranges/size.h
__ranges/subrange.h
+ __ranges/take_view.h
__ranges/transform_view.h
__ranges/view_interface.h
__split_buffer
diff --git a/libcxx/include/__ranges/copyable_box.h b/libcxx/include/__ranges/copyable_box.h
index f2d3843f79f54..553d2b9ee3e29 100644
--- a/libcxx/include/__ranges/copyable_box.h
+++ b/libcxx/include/__ranges/copyable_box.h
@@ -91,6 +91,10 @@ namespace ranges {
_LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; }
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return __val_.operator->(); }
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return __val_.operator->(); }
+
_LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); }
};
@@ -162,6 +166,10 @@ namespace ranges {
_LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; }
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return _VSTD::addressof(__val_); }
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return _VSTD::addressof(__val_); }
+
_LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; }
};
} // namespace ranges
diff --git a/libcxx/include/__ranges/single_view.h b/libcxx/include/__ranges/single_view.h
new file mode 100644
index 0000000000000..ef9822d211480
--- /dev/null
+++ b/libcxx/include/__ranges/single_view.h
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef _LIBCPP___RANGES_SINGLE_VIEW_H
+#define _LIBCPP___RANGES_SINGLE_VIEW_H
+
+#include <__config>
+#include <__ranges/view_interface.h>
+#include <__ranges/copyable_box.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ template<copy_constructible _Tp>
+ requires is_object_v<_Tp>
+ class single_view : public view_interface<single_view<_Tp>> {
+ __copyable_box<_Tp> __value_;
+
+ public:
+ _LIBCPP_HIDE_FROM_ABI
+ single_view() requires default_initializable<_Tp> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit single_view(const _Tp& __t) : __value_(in_place, __t) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit single_view(_Tp&& __t) : __value_(in_place, _VSTD::move(__t)) {}
+
+ template<class... _Args>
+ requires constructible_from<_Tp, _Args...>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit single_view(in_place_t, _Args&&... __args)
+ : __value_{in_place, _VSTD::forward<_Args>(__args)...} {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Tp* begin() noexcept { return data(); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr const _Tp* begin() const noexcept { return data(); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Tp* end() noexcept { return data() + 1; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr const _Tp* end() const noexcept { return data() + 1; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ static constexpr size_t size() noexcept { return 1; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Tp* data() noexcept { return __value_.operator->(); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr const _Tp* data() const noexcept { return __value_.operator->(); }
+ };
+
+ template<class _Tp>
+ single_view(_Tp) -> single_view<_Tp>;
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_SINGLE_VIEW_H
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index cd77a4a62ff5e..ee6f3c3e0a4d4 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -632,6 +632,7 @@ module std [system] {
module non_propagating_cache { private header "__ranges/non_propagating_cache.h" }
module ref_view { private header "__ranges/ref_view.h" }
module size { private header "__ranges/size.h" }
+ module single_view { private header "__ranges/single_view.h" }
module subrange { private header "__ranges/subrange.h" }
module take_view { private header "__ranges/take_view.h" }
module transform_view { private header "__ranges/transform_view.h" }
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 0a78e0097bff7..f1a3f5e6cabba 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -162,6 +162,10 @@ namespace std::ranges {
template<class T>
inline constexpr bool enable_borrowed_range<take_view<T>> = enable_borrowed_range<T>;
+
+ template<copy_constructible T>
+ requires is_object_v<T>
+ class single_view;
}
*/
@@ -179,9 +183,10 @@ namespace std::ranges {
#include <__ranges/enable_borrowed_range.h>
#include <__ranges/enable_view.h>
#include <__ranges/ref_view.h>
-#include <__ranges/take_view.h>
+#include <__ranges/single_view.h>
#include <__ranges/size.h>
#include <__ranges/subrange.h>
+#include <__ranges/take_view.h>
#include <__ranges/transform_view.h>
#include <__ranges/view_interface.h>
#include <compare> // Required by the standard.
diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/single_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/single_view.module.verify.cpp
new file mode 100644
index 0000000000000..eb6e276d0a452
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/single_view.module.verify.cpp
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: modules-build
+
+// WARNING: This test was generated by 'generate_private_header_tests.py'
+// and should not be edited manually.
+
+// expected-error@*:* {{use of private header from outside its module: '__ranges/single_view.h'}}
+#include <__ranges/single_view.h>
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp
new file mode 100644
index 0000000000000..706ca9b801658
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/arrow.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// T* <copyable-box>::operator->()
+// const T* <copyable-box>::operator->() const
+
+#include <ranges>
+
+#include <cassert>
+#include <type_traits>
+#include <utility> // in_place_t
+
+#include "types.h"
+
+template<class T>
+constexpr void check() {
+ // non-const version
+ {
+ std::ranges::__copyable_box<T> x(std::in_place, 10);
+ T* result = x.operator->();
+ static_assert(noexcept(x.operator->()));
+ assert(result->value == 10);
+ assert(x->value == 10);
+ }
+
+ // const version
+ {
+ std::ranges::__copyable_box<T> const x(std::in_place, 10);
+ const T* result = x.operator->();
+ static_assert(noexcept(x.operator->()));
+ assert(result->value == 10);
+ assert(x->value == 10);
+ }
+}
+
+constexpr bool test() {
+ check<CopyConstructible>(); // primary template
+ check<Copyable>(); // optimization #1
+ check<NothrowCopyConstructible>(); // optimization #2
+ return true;
+}
+
+int main(int, char**) {
+ assert(test());
+ static_assert(test());
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
index 05f79b2e52075..2ede1781f8f54 100644
--- a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
@@ -32,6 +32,10 @@ struct SizeMember {
constexpr size_t size() { return 42; }
};
+struct StaticSizeMember {
+ constexpr static size_t size() { return 42; }
+};
+
static_assert(!std::is_invocable_v<RangeSizeT, const SizeMember>);
struct SizeFunction {
@@ -82,6 +86,9 @@ bool constexpr testHasSizeMember() {
assert(std::ranges::size(SizeMemberSigned()) == 42);
ASSERT_SAME_TYPE(decltype(std::ranges::size(SizeMemberSigned())), long);
+ assert(std::ranges::size(StaticSizeMember()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(StaticSizeMember())), size_t);
+
return true;
}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/assign.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/assign.pass.cpp
new file mode 100644
index 0000000000000..efa8af3684882
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/assign.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10, gcc-11
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// Tests that <value_> is a <copyable-box>.
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct NotAssignable {
+ NotAssignable() = default;
+ NotAssignable(const NotAssignable&) = default;
+ NotAssignable(NotAssignable&&) = default;
+
+ NotAssignable& operator=(const NotAssignable&) = delete;
+ NotAssignable& operator=(NotAssignable&&) = delete;
+};
+
+constexpr bool test() {
+ const std::ranges::single_view<NotAssignable> a;
+ std::ranges::single_view<NotAssignable> b;
+ b = a;
+ b = std::move(a);
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/begin.pass.cpp
new file mode 100644
index 0000000000000..1df29e81b834b
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/begin.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// constexpr T* begin() noexcept;
+// constexpr const T* begin() const noexcept;
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Empty {};
+struct BigType { char buffer[64] = {10}; };
+
+constexpr bool test() {
+ {
+ auto sv = std::ranges::single_view<int>(42);
+ assert(*sv.begin() == 42);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), int*);
+ static_assert(noexcept(sv.begin()));
+ }
+ {
+ const auto sv = std::ranges::single_view<int>(42);
+ assert(*sv.begin() == 42);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), const int*);
+ static_assert(noexcept(sv.begin()));
+ }
+
+ {
+ auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.begin() != nullptr);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), Empty*);
+ }
+ {
+ const auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.begin() != nullptr);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), const Empty*);
+ }
+
+ {
+ auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.begin()->buffer[0] == 10);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), BigType*);
+ }
+ {
+ const auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.begin()->buffer[0] == 10);
+
+ ASSERT_SAME_TYPE(decltype(sv.begin()), const BigType*);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/ctad.compile.pass.cpp
new file mode 100644
index 0000000000000..aed366ba8e9d6
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/ctad.compile.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// template<class T>
+// single_view(T) -> single_view<T>;
+
+#include <ranges>
+
+#include <cassert>
+#include <concepts>
+
+#include "test_iterators.h"
+
+struct Empty {};
+
+static_assert(std::same_as<
+ decltype(std::ranges::single_view(Empty())),
+ std::ranges::single_view<Empty>
+>);
+
+static_assert(std::same_as<
+ decltype(std::ranges::single_view(std::declval<Empty&>())),
+ std::ranges::single_view<Empty>
+>);
+
+static_assert(std::same_as<
+ decltype(std::ranges::single_view(std::declval<Empty&&>())),
+ std::ranges::single_view<Empty>
+>);
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.default.pass.cpp
new file mode 100644
index 0000000000000..304926d2d80f0
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.default.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// single_view() requires default_initializable<T> = default;
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct BigType { char buffer[64] = {10}; };
+
+template<bool DefaultCtorEnabled>
+struct IsDefaultConstructible {
+ IsDefaultConstructible() requires DefaultCtorEnabled = default;
+};
+
+constexpr bool test() {
+ static_assert( std::default_initializable<std::ranges::single_view<IsDefaultConstructible<true>>>);
+ static_assert(!std::default_initializable<std::ranges::single_view<IsDefaultConstructible<false>>>);
+
+ {
+ std::ranges::single_view<BigType> sv;
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+ {
+ const std::ranges::single_view<BigType> sv;
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/ctor.in_place.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.in_place.pass.cpp
new file mode 100644
index 0000000000000..8f7f0a4326b61
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.in_place.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// template<class... Args>
+// requires constructible_from<T, Args...>
+// constexpr explicit single_view(in_place_t, Args&&... args);
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct TakesTwoInts {
+ int a_, b_;
+ constexpr TakesTwoInts(int a, int b) : a_(a), b_(b) {}
+};
+
+constexpr bool test() {
+ {
+ std::ranges::single_view<TakesTwoInts> sv(std::in_place, 1, 2);
+ assert(sv.data()->a_ == 1);
+ assert(sv.data()->b_ == 2);
+ assert(sv.size() == 1);
+ }
+ {
+ const std::ranges::single_view<TakesTwoInts> sv(std::in_place, 1, 2);
+ assert(sv.data()->a_ == 1);
+ assert(sv.data()->b_ == 2);
+ assert(sv.size() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.value.pass.cpp
new file mode 100644
index 0000000000000..fa95cf5005edb
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/ctor.value.pass.cpp
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// constexpr explicit single_view(const T& t);
+// constexpr explicit single_view(T&& t);
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Empty {};
+struct BigType { char buffer[64] = {10}; };
+
+constexpr bool test() {
+ {
+ BigType bt;
+ std::ranges::single_view<BigType> sv(bt);
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+ {
+ const BigType bt;
+ const std::ranges::single_view<BigType> sv(bt);
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+
+ {
+ BigType bt;
+ std::ranges::single_view<BigType> sv(std::move(bt));
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+ {
+ const BigType bt;
+ const std::ranges::single_view<BigType> sv(std::move(bt));
+ assert(sv.data()->buffer[0] == 10);
+ assert(sv.size() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/data.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/data.pass.cpp
new file mode 100644
index 0000000000000..9c590904894e3
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/data.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// constexpr T* data() noexcept;
+// constexpr const T* data() const noexcept;
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Empty {};
+struct BigType { char buffer[64] = {10}; };
+
+constexpr bool test() {
+ {
+ auto sv = std::ranges::single_view<int>(42);
+ assert(*sv.data() == 42);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), int*);
+ static_assert(noexcept(sv.data()));
+ }
+ {
+ const auto sv = std::ranges::single_view<int>(42);
+ assert(*sv.data() == 42);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), const int*);
+ static_assert(noexcept(sv.data()));
+ }
+
+ {
+ auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.data() != nullptr);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), Empty*);
+ }
+ {
+ const auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.data() != nullptr);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), const Empty*);
+ }
+
+ {
+ auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.data()->buffer[0] == 10);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), BigType*);
+ }
+ {
+ const auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.data()->buffer[0] == 10);
+
+ ASSERT_SAME_TYPE(decltype(sv.data()), const BigType*);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/end.pass.cpp
new file mode 100644
index 0000000000000..d407ca0029d3f
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/end.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// constexpr T* end() noexcept;
+// constexpr const T* end() const noexcept;
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Empty {};
+struct BigType { char buffer[64] = {10}; };
+
+constexpr bool test() {
+ {
+ auto sv = std::ranges::single_view<int>(42);
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), int*);
+ static_assert(noexcept(sv.end()));
+ }
+ {
+ const auto sv = std::ranges::single_view<int>(42);
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), const int*);
+ static_assert(noexcept(sv.end()));
+ }
+
+ {
+ auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), Empty*);
+ }
+ {
+ const auto sv = std::ranges::single_view<Empty>(Empty());
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), const Empty*);
+ }
+
+ {
+ auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), BigType*);
+ }
+ {
+ const auto sv = std::ranges::single_view<BigType>(BigType());
+ assert(sv.end() == sv.begin() + 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.end()), const BigType*);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/range_concept_conformance.compile.pass.cpp
new file mode 100644
index 0000000000000..63b817f7b192f
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/range_concept_conformance.compile.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// Test that single_view conforms to range and view concepts.
+
+#include <ranges>
+
+#include <cassert>
+#include <concepts>
+
+#include "test_iterators.h"
+
+struct Empty {};
+
+static_assert(std::ranges::contiguous_range<std::ranges::single_view<Empty>>);
+static_assert(std::ranges::contiguous_range<const std::ranges::single_view<Empty>>);
+static_assert(std::ranges::view<std::ranges::single_view<Empty>>);
+static_assert(std::ranges::view<std::ranges::single_view<const Empty>>);
+static_assert(std::ranges::contiguous_range<const std::ranges::single_view<const Empty>>);
+static_assert(std::ranges::view<std::ranges::single_view<int>>);
+static_assert(std::ranges::view<std::ranges::single_view<const int>>);
+static_assert(std::ranges::contiguous_range<const std::ranges::single_view<const int>>);
diff --git a/libcxx/test/std/ranges/range.factories/range.single.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.single.view/size.pass.cpp
new file mode 100644
index 0000000000000..87054a75fa037
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.single.view/size.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// static constexpr size_t size() noexcept;
+
+#include <ranges>
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ auto sv = std::ranges::single_view<int>(42);
+ assert(sv.size() == 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.size()), size_t);
+ static_assert(noexcept(sv.size()));
+ }
+ {
+ const auto sv = std::ranges::single_view<int>(42);
+ assert(sv.size() == 1);
+
+ ASSERT_SAME_TYPE(decltype(sv.size()), size_t);
+ static_assert(noexcept(sv.size()));
+ }
+ {
+ auto sv = std::ranges::single_view<int>(42);
+ assert(std::ranges::size(sv) == 1);
+
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(sv)), size_t);
+ static_assert(noexcept(std::ranges::size(sv)));
+ }
+ {
+ const auto sv = std::ranges::single_view<int>(42);
+ assert(std::ranges::size(sv) == 1);
+
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(sv)), size_t);
+ static_assert(noexcept(std::ranges::size(sv)));
+ }
+
+ // Test that it's static.
+ {
+ assert(std::ranges::single_view<int>::size() == 1);
+
+ ASSERT_SAME_TYPE(decltype(std::ranges::single_view<int>::size()), size_t);
+ static_assert(noexcept(std::ranges::single_view<int>::size()));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
More information about the libcxx-commits
mailing list