[libcxx-commits] [libcxx] [libc++] P3168R2 Give std::optional Range Support (PR #146491)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 1 07:01:50 PDT 2025
https://github.com/dywoq updated https://github.com/llvm/llvm-project/pull/146491
>From 4b9c76ba6e541102fdaa1e5839e65e014c49263f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 22:27:37 +0300
Subject: [PATCH 01/25] [libcxx] add ranges::enable_view<optional<_T>> = true
and format_kind<optional<_T>> = range_format::disabled
---
libcxx/.clangd | 2 ++
libcxx/include/optional | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 libcxx/.clangd
diff --git a/libcxx/.clangd b/libcxx/.clangd
new file mode 100644
index 0000000000000..8a80936175292
--- /dev/null
+++ b/libcxx/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+ Add: [--std=c++2c]
\ No newline at end of file
diff --git a/libcxx/include/optional b/libcxx/include/optional
index fa32d75ef86dd..f7d27c673fa52 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -102,6 +102,8 @@ namespace std {
class optional {
public:
using value_type = T;
+ using iterator = implementation-defined; // see [optional.iterators] // since C++26
+ using const_iterator = implementation-defined; // see [optional.iterators] // since C++26
// [optional.ctor], constructors
constexpr optional() noexcept;
@@ -135,6 +137,12 @@ namespace std {
// [optional.swap], swap
void swap(optional &) noexcept(see below ); // constexpr in C++20
+ // [optional.iterators], iterator support
+ constexpr iterator begin() noexcept; // since C++26
+ constexpr const_iterator begin() const noexcept; // since C++26
+ constexpr iterator end() noexcept; // since C++26
+ constexpr const_iterator end() const noexcept; // since C++26
+
// [optional.observe], observers
constexpr T const *operator->() const noexcept;
constexpr T *operator->() noexcept;
@@ -173,6 +181,11 @@ namespace std {
template<class T>
optional(T) -> optional<T>;
+ template<class T>
+ constexpr bool ranges::enable_view<optional<T>> = true; // since C++26
+ template<class T>
+ constexpr auto format_kind<optional<T>> = range_format::disabled; // since C++26
+
} // namespace std
*/
@@ -187,6 +200,7 @@ namespace std {
# include <__concepts/invocable.h>
# include <__config>
# include <__exception/exception.h>
+# include <__format/range_default_formatter.h>
# include <__functional/hash.h>
# include <__functional/invoke.h>
# include <__functional/unary_function.h>
@@ -578,6 +592,14 @@ struct __is_std_optional : false_type {};
template <class _Tp>
struct __is_std_optional<optional<_Tp>> : true_type {};
+# if _LIBCPP_STD_VER >= 26
+template <class _T>
+constexpr bool ranges::enable_view<optional<_T>> = true;
+
+template <class _T>
+constexpr auto format_kind<optional<_T>> = range_format::disabled;
+# endif
+
template <class _Tp>
class _LIBCPP_DECLSPEC_EMPTY_BASES optional
: private __optional_move_assign_base<_Tp>,
>From ebda4e4e97c46deae63f1139aa84016b704308b7 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 22:39:17 +0300
Subject: [PATCH 02/25] [libcxx] add forward declaration of __optional_iterator
in <optional>
---
libcxx/include/optional | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index f7d27c673fa52..ccd06c7c9f5e7 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -102,7 +102,7 @@ namespace std {
class optional {
public:
using value_type = T;
- using iterator = implementation-defined; // see [optional.iterators] // since C++26
+ using iterator = implementation-defined; // see [optional.iterators] // since C++26
using const_iterator = implementation-defined; // see [optional.iterators] // since C++26
// [optional.ctor], constructors
@@ -580,6 +580,15 @@ using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
template <class _Tp>
class optional;
+# if _LIBCPP_STD_VER >= 26
+
+enum class __optional_iterator_kind { not_as_const, as_const };
+
+template <__optional_iterator_kind _Kind>
+class __optional_iterator;
+
+# endif // _LIBCPP_STD_VER >= 26
+
# if _LIBCPP_STD_VER >= 20
template <class _Tp>
@@ -593,12 +602,14 @@ template <class _Tp>
struct __is_std_optional<optional<_Tp>> : true_type {};
# if _LIBCPP_STD_VER >= 26
+
template <class _T>
constexpr bool ranges::enable_view<optional<_T>> = true;
template <class _T>
constexpr auto format_kind<optional<_T>> = range_format::disabled;
-# endif
+
+# endif // _LIBCPP_STD_VER >= 26
template <class _Tp>
class _LIBCPP_DECLSPEC_EMPTY_BASES optional
@@ -610,6 +621,13 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
public:
using value_type = _Tp;
+# if _LIBCPP_STD_VER >= 26
+
+ using iterator = __optional_iterator<__optional_iterator_kind::not_as_const>;
+ using const_iterator = __optional_iterator<__optional_iterator_kind::as_const>;
+
+# endif // _LIBCPP_STD_VER >= 26
+
using __trivially_relocatable _LIBCPP_NODEBUG =
conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
using __replaceable _LIBCPP_NODEBUG = conditional_t<__is_replaceable_v<_Tp>, optional, void>;
>From 6e97c3411107ac5bf8d926f4a1a5f99fae1f2958 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 22:54:22 +0300
Subject: [PATCH 03/25] [libcxx] add __optional_iterator
---
libcxx/include/optional | 55 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index ccd06c7c9f5e7..c5fe9370262a9 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -584,7 +584,7 @@ class optional;
enum class __optional_iterator_kind { not_as_const, as_const };
-template <__optional_iterator_kind _Kind>
+template <typename _Tp, __optional_iterator_kind _Kind>
class __optional_iterator;
# endif // _LIBCPP_STD_VER >= 26
@@ -609,6 +609,59 @@ constexpr bool ranges::enable_view<optional<_T>> = true;
template <class _T>
constexpr auto format_kind<optional<_T>> = range_format::disabled;
+template <typename _Tp, __optional_iterator_kind _Kind>
+class __optional_iterator {
+public:
+ using value_type = _Tp;
+ using difference_type = std::ptrdiff_t;
+ using pointer = _Tp*;
+ using reference = _Tp&;
+ using iterator_category = std::forward_iterator_tag;
+
+private:
+ pointer __ptr_;
+ _LIBCPP_HIDE_FROM_ABI explicit __optional_iterator(pointer __ptr) : __ptr_(__ptr) {}
+ _LIBCPP_HIDE_FROM_ABI friend class optional<std::remove_const_t<_Tp>>;
+ _LIBCPP_HIDE_FROM_ABI friend class optional<const _Tp>;
+
+public:
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator() : __ptr_(nullptr) {}
+
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator(const __optional_iterator&) = default;
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator& operator=(const __optional_iterator&) = default;
+
+ _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+ if (__ptr_ == nullptr)
+ throw std::runtime_error("dereferencing end iterator");
+ return *__ptr_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI reference operator->() const {
+ if (__ptr_ == nullptr)
+ throw std::runtime_error("dereferencing end iterator");
+ return *__ptr_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator operator++() {
+ __ptr_ = nullptr;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator operator++(int) {
+ __optional_iterator __tmp = *this;
+ __ptr_ = nullptr;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI bool operator==(const __optional_iterator& __other) const { return __ptr_ == __other.__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI bool operator!=(const __optional_iterator& __other) const { return __ptr_ != __other.__ptr_; }
+
+ template <typename _Ut = _Tp, __optional_iterator_kind _UKind = _Kind>
+ _LIBCPP_HIDE_FROM_ABI operator __optional_iterator<const _Tp, _UKind>() const {
+ return __optional_iterator<const _Tp, _UKind>(static_cast<const _Tp*>(__ptr_));
+ }
+};
+
# endif // _LIBCPP_STD_VER >= 26
template <class _Tp>
>From ef525626d0a8cb55c47b597fc47ee758421daf91 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 10:32:44 +0300
Subject: [PATCH 04/25] [libcxxx] add begin() and end() to std::optional class
---
libcxx/include/optional | 44 +++++++++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 13 deletions(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index c5fe9370262a9..edca0003f687b 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -582,9 +582,7 @@ class optional;
# if _LIBCPP_STD_VER >= 26
-enum class __optional_iterator_kind { not_as_const, as_const };
-
-template <typename _Tp, __optional_iterator_kind _Kind>
+template <typename _Tp>
class __optional_iterator;
# endif // _LIBCPP_STD_VER >= 26
@@ -609,7 +607,7 @@ constexpr bool ranges::enable_view<optional<_T>> = true;
template <class _T>
constexpr auto format_kind<optional<_T>> = range_format::disabled;
-template <typename _Tp, __optional_iterator_kind _Kind>
+template <typename _Tp>
class __optional_iterator {
public:
using value_type = _Tp;
@@ -632,17 +630,17 @@ public:
_LIBCPP_HIDE_FROM_ABI reference operator*() const {
if (__ptr_ == nullptr)
- throw std::runtime_error("dereferencing end iterator");
+ std::__throw_runtime_error("deferencering end iterator");
return *__ptr_;
}
- _LIBCPP_HIDE_FROM_ABI reference operator->() const {
+ _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
if (__ptr_ == nullptr)
- throw std::runtime_error("dereferencing end iterator");
+ std::__throw_runtime_error("deferencering end iterator");
return *__ptr_;
}
- _LIBCPP_HIDE_FROM_ABI __optional_iterator operator++() {
+ _LIBCPP_HIDE_FROM_ABI __optional_iterator& operator++() {
__ptr_ = nullptr;
return *this;
}
@@ -656,9 +654,11 @@ public:
_LIBCPP_HIDE_FROM_ABI bool operator==(const __optional_iterator& __other) const { return __ptr_ == __other.__ptr_; }
_LIBCPP_HIDE_FROM_ABI bool operator!=(const __optional_iterator& __other) const { return __ptr_ != __other.__ptr_; }
- template <typename _Ut = _Tp, __optional_iterator_kind _UKind = _Kind>
- _LIBCPP_HIDE_FROM_ABI operator __optional_iterator<const _Tp, _UKind>() const {
- return __optional_iterator<const _Tp, _UKind>(static_cast<const _Tp*>(__ptr_));
+ template <typename _Ut = _Tp>
+ _LIBCPP_HIDE_FROM_ABI operator __optional_iterator<const _Tp>() const
+ requires(!std::is_const_v<_Ut>)
+ {
+ return __optional_iterator<const _Tp>(static_cast<const _Tp*>(__ptr_));
}
};
@@ -676,8 +676,8 @@ public:
# if _LIBCPP_STD_VER >= 26
- using iterator = __optional_iterator<__optional_iterator_kind::not_as_const>;
- using const_iterator = __optional_iterator<__optional_iterator_kind::as_const>;
+ using iterator = __optional_iterator<_Tp>;
+ using const_iterator = __optional_iterator<_Tp>;
# endif // _LIBCPP_STD_VER >= 26
@@ -1069,6 +1069,24 @@ public:
}
# endif // _LIBCPP_STD_VER >= 23
+# if _LIBCPP_STD_VER >= 26
+
+ _LIBCPP_HIDE_FROM_ABI iterator begin() {
+ if (!this->has_value())
+ return this->end();
+ return iterator(reinterpret_cast<_Tp*>(this->__get()));
+ }
+ _LIBCPP_HIDE_FROM_ABI const_iterator begin() const {
+ if (!this->has_value())
+ return this->end();
+ return const_iterator(reinterpret_cast<_Tp*>(this->value()));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI iterator end() { return iterator(nullptr); }
+ _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return const_iterator(nullptr); }
+
+# endif
+
using __base::reset;
};
>From 820d96c67320eeffb67d595441558079aaaa899f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 10:59:18 +0300
Subject: [PATCH 05/25] [libcxx] update includes in <optional> header
---
libcxx/include/optional | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index edca0003f687b..235a6682d6448 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -137,7 +137,7 @@ namespace std {
// [optional.swap], swap
void swap(optional &) noexcept(see below ); // constexpr in C++20
- // [optional.iterators], iterator support
+ // [optional.iterators], iterator support
constexpr iterator begin() noexcept; // since C++26
constexpr const_iterator begin() const noexcept; // since C++26
constexpr iterator end() noexcept; // since C++26
@@ -200,6 +200,7 @@ namespace std {
# include <__concepts/invocable.h>
# include <__config>
# include <__exception/exception.h>
+# include <__format/format_context.h>
# include <__format/range_default_formatter.h>
# include <__functional/hash.h>
# include <__functional/invoke.h>
>From 5fc696bdc95883892b04fd6f076095ffc141ea1d Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:00:10 +0300
Subject: [PATCH 06/25] [libcxx] add comment
---
libcxx/include/optional | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 235a6682d6448..1942d0ce14336 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -1070,6 +1070,7 @@ public:
}
# endif // _LIBCPP_STD_VER >= 23
+// P3168R2
# if _LIBCPP_STD_VER >= 26
_LIBCPP_HIDE_FROM_ABI iterator begin() {
>From 162170ce8c1cee4e170e8995a2dfd49967593416 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:03:46 +0300
Subject: [PATCH 07/25] [libcxx] remove unimplemented: True parameter in
generate_feature_test_macro_components.py
---
libcxx/utils/generate_feature_test_macro_components.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index edd7b124a1fb3..7be4880428d58 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1004,7 +1004,6 @@ def add_version_header(tc):
"name": "__cpp_lib_optional_range_support",
"values": {"c++26": 202406}, # P3168R2 Give std::optional Range Support
"headers": ["optional"],
- "unimplemented": True,
},
{
"name": "__cpp_lib_out_ptr",
>From f968252c6a6c8e098832e873a9223ec31f7e5449 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:07:48 +0300
Subject: [PATCH 08/25] [libcxx] update <version> header
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/include/version | 2 +-
.../optional.version.compile.pass.cpp | 16 +++++-----------
.../version.version.compile.pass.cpp | 16 +++++-----------
4 files changed, 12 insertions(+), 24 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3c635e5e46bbd..28e8f805e1843 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -476,7 +476,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_not_fn`` ``202306L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_optional_range_support`` *unimplemented*
+ ``__cpp_lib_optional_range_support`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` ``202311L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/include/version b/libcxx/include/version
index 91fe48351e161..6096185efc865 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -581,7 +581,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_mdspan 202406L
# undef __cpp_lib_not_fn
# define __cpp_lib_not_fn 202306L
-// # define __cpp_lib_optional_range_support 202406L
+# define __cpp_lib_optional_range_support 202406L
# undef __cpp_lib_out_ptr
# define __cpp_lib_out_ptr 202311L
// # define __cpp_lib_philox_engine 202406L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
index 32685972d6019..ece2fe81b7c13 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
@@ -152,17 +152,11 @@
# error "__cpp_lib_optional should have the value 202110L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_optional_range_support
-# error "__cpp_lib_optional_range_support should be defined in c++26"
-# endif
-# if __cpp_lib_optional_range_support != 202406L
-# error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
-# endif
-# else
-# ifdef __cpp_lib_optional_range_support
-# error "__cpp_lib_optional_range_support should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_optional_range_support
+# error "__cpp_lib_optional_range_support should be defined in c++26"
+# endif
+# if __cpp_lib_optional_range_support != 202406L
+# error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
# endif
#endif // TEST_STD_VER > 23
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index e546719142231..09063e5a80e17 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -7377,17 +7377,11 @@
# error "__cpp_lib_optional should have the value 202110L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_optional_range_support
-# error "__cpp_lib_optional_range_support should be defined in c++26"
-# endif
-# if __cpp_lib_optional_range_support != 202406L
-# error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
-# endif
-# else
-# ifdef __cpp_lib_optional_range_support
-# error "__cpp_lib_optional_range_support should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_optional_range_support
+# error "__cpp_lib_optional_range_support should be defined in c++26"
+# endif
+# if __cpp_lib_optional_range_support != 202406L
+# error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
# endif
# ifndef __cpp_lib_out_ptr
>From 06109ed45e53775186e4074a126174d65e95708f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:45:28 +0300
Subject: [PATCH 09/25] [libcxx] write optional.range tests
---
.../optional.range/iteration.pass.cpp | 20 +++++++++++++++++++
.../satisfies_range_concept.pass.cpp | 19 ++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
create mode 100644 libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
diff --git a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
new file mode 100644
index 0000000000000..8ab1c099d30b5
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: std-at-least-c++26
+
+#include <iostream>
+#include <optional>
+
+int main() {
+ std::optional<int> val = 2;
+ for (const auto& elem : val) {
+ std::cout << elem << std::endl;
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
new file mode 100644
index 0000000000000..96ba4c0903067
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: std-at-least-c++26
+
+#include <iostream>
+#include <optional>
+#include <ranges>
+
+int main() {
+ bool status = std::ranges::range<std::optional<int>>;
+ std::cout << "std::ranges::range<std::optional<int>> is " << status << std::endl;
+ return 0;
+}
\ No newline at end of file
>From fc75fe044d7070fafe6b4f27c8ca71fad84137ca Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:54:27 +0300
Subject: [PATCH 10/25] [libcxx] add optional.range.runtime_error.fail test
---
.../optional.range/runtime_error.fail.cpp | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
new file mode 100644
index 0000000000000..7e27fbf0d1f22
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: std-at-least-c++26
+
+#include <iostream>
+#include <optional>
+
+int main() {
+ std::optional<int> val = 2;
+ auto end = val.end();
+ auto s = *end;
+ (void)s;
+ return 0;
+}
\ No newline at end of file
>From f9395288e1252bfd4b8705b38bec4fa9ee61dfe6 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:58:10 +0300
Subject: [PATCH 11/25] [libcxx] remove unused include
---
...runtime_error.fail.cpp => runtime_error.compile.fail.cpp} | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
rename libcxx/test/std/utilities/optional/optional.range/{runtime_error.fail.cpp => runtime_error.compile.fail.cpp} (87%)
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
similarity index 87%
rename from libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
rename to libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
index 7e27fbf0d1f22..554fbd8af37fa 100644
--- a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
@@ -8,13 +8,12 @@
// UNSUPPORTED: std-at-least-c++26
-#include <iostream>
+#include "../../../../support/assert_macros.h"
#include <optional>
int main() {
std::optional<int> val = 2;
auto end = val.end();
- auto s = *end;
- (void)s;
+ TEST_DOES_NOT_THROW(*end);
return 0;
}
\ No newline at end of file
>From fdc917b0d87ed8504c25fc5a86ad2b3eb224d0d1 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:58:32 +0300
Subject: [PATCH 12/25] [libcxx] change path to assert_macros.h
---
.../optional/optional.range/runtime_error.compile.fail.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
index 554fbd8af37fa..fa74c2b477efd 100644
--- a/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
@@ -8,7 +8,7 @@
// UNSUPPORTED: std-at-least-c++26
-#include "../../../../support/assert_macros.h"
+#include "assert_macros.h"
#include <optional>
int main() {
>From e704aba28045f536888caed99d246a3c7238bbb1 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 11:59:25 +0300
Subject: [PATCH 13/25] [libcxx] remove .clangd
---
libcxx/.clangd | 2 --
1 file changed, 2 deletions(-)
delete mode 100644 libcxx/.clangd
diff --git a/libcxx/.clangd b/libcxx/.clangd
deleted file mode 100644
index 8a80936175292..0000000000000
--- a/libcxx/.clangd
+++ /dev/null
@@ -1,2 +0,0 @@
-CompileFlags:
- Add: [--std=c++2c]
\ No newline at end of file
>From f294f986a71f574d0fb87c3306c3672d564a7c77 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 12:02:52 +0300
Subject: [PATCH 14/25] [libcxx] rename test
---
.../{runtime_error.compile.fail.cpp => runtime_error.fail.cpp} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename libcxx/test/std/utilities/optional/optional.range/{runtime_error.compile.fail.cpp => runtime_error.fail.cpp} (100%)
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
similarity index 100%
rename from libcxx/test/std/utilities/optional/optional.range/runtime_error.compile.fail.cpp
rename to libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
>From a720391ab78b447a0e18b94efa50329a144a250f Mon Sep 17 00:00:00 2001
From: dywoq <138208549+dywoq at users.noreply.github.com>
Date: Tue, 1 Jul 2025 14:39:17 +0300
Subject: [PATCH 15/25] [libcxx] change iterator_category to
random_access_iterator_tag <optional>
Co-authored-by: A. Jiang <de34 at live.cn>
---
libcxx/include/optional | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 1942d0ce14336..62718da9d775a 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -615,7 +615,8 @@ public:
using difference_type = std::ptrdiff_t;
using pointer = _Tp*;
using reference = _Tp&;
- using iterator_category = std::forward_iterator_tag;
+ using iterator_category = random_access_iterator_tag;
+ using iterator_concept = contiguous_iterator_tag;
private:
pointer __ptr_;
>From 4bfc9bbfa4f4710e13b2b284b826a547d1b4e87d Mon Sep 17 00:00:00 2001
From: dywoq <138208549+dywoq at users.noreply.github.com>
Date: Tue, 1 Jul 2025 14:43:34 +0300
Subject: [PATCH 16/25] [libcxx] remove operator!= for __optional_iterator in
<optional>
Co-authored-by: A. Jiang <de34 at live.cn>
---
libcxx/include/optional | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 62718da9d775a..4d4f69dbacbcf 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -654,7 +654,6 @@ public:
}
_LIBCPP_HIDE_FROM_ABI bool operator==(const __optional_iterator& __other) const { return __ptr_ == __other.__ptr_; }
- _LIBCPP_HIDE_FROM_ABI bool operator!=(const __optional_iterator& __other) const { return __ptr_ != __other.__ptr_; }
template <typename _Ut = _Tp>
_LIBCPP_HIDE_FROM_ABI operator __optional_iterator<const _Tp>() const
>From 26974eb40fb08d8efe2737de4f5d4f2ad273714e Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 15:11:33 +0300
Subject: [PATCH 17/25] [libcxx] add constexpr to __optional_iterator,
optional<T>::begin and optional<T>::end
---
libcxx/include/optional | 43 +++++++++++++++++------------------------
1 file changed, 18 insertions(+), 25 deletions(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 4d4f69dbacbcf..a8a88a1614b07 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -620,43 +620,36 @@ public:
private:
pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI explicit __optional_iterator(pointer __ptr) : __ptr_(__ptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_iterator(pointer __ptr) : __ptr_(__ptr) {}
_LIBCPP_HIDE_FROM_ABI friend class optional<std::remove_const_t<_Tp>>;
_LIBCPP_HIDE_FROM_ABI friend class optional<const _Tp>;
public:
- _LIBCPP_HIDE_FROM_ABI __optional_iterator() : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator() : __ptr_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI __optional_iterator(const __optional_iterator&) = default;
- _LIBCPP_HIDE_FROM_ABI __optional_iterator& operator=(const __optional_iterator&) = default;
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator(const __optional_iterator&) = default;
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator=(const __optional_iterator&) = default;
- _LIBCPP_HIDE_FROM_ABI reference operator*() const {
- if (__ptr_ == nullptr)
- std::__throw_runtime_error("deferencering end iterator");
- return *__ptr_;
- }
-
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
- if (__ptr_ == nullptr)
- std::__throw_runtime_error("deferencering end iterator");
- return *__ptr_;
- }
+ _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return *__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { return *__ptr_; }
- _LIBCPP_HIDE_FROM_ABI __optional_iterator& operator++() {
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator++() {
__ptr_ = nullptr;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __optional_iterator operator++(int) {
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator++(int) {
__optional_iterator __tmp = *this;
__ptr_ = nullptr;
return __tmp;
}
- _LIBCPP_HIDE_FROM_ABI bool operator==(const __optional_iterator& __other) const { return __ptr_ == __other.__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const __optional_iterator& __other) const {
+ return __ptr_ == __other.__ptr_;
+ }
template <typename _Ut = _Tp>
- _LIBCPP_HIDE_FROM_ABI operator __optional_iterator<const _Tp>() const
+ _LIBCPP_HIDE_FROM_ABI constexpr operator __optional_iterator<const _Tp>() const
requires(!std::is_const_v<_Ut>)
{
return __optional_iterator<const _Tp>(static_cast<const _Tp*>(__ptr_));
@@ -1073,19 +1066,19 @@ public:
// P3168R2
# if _LIBCPP_STD_VER >= 26
- _LIBCPP_HIDE_FROM_ABI iterator begin() {
+ _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() {
if (!this->has_value())
return this->end();
- return iterator(reinterpret_cast<_Tp*>(this->__get()));
+ return iterator(static_cast<_Tp*>(this->__get()));
}
- _LIBCPP_HIDE_FROM_ABI const_iterator begin() const {
+ _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const {
if (!this->has_value())
return this->end();
- return const_iterator(reinterpret_cast<_Tp*>(this->value()));
+ return const_iterator(static_cast<_Tp*>(this->value()));
}
- _LIBCPP_HIDE_FROM_ABI iterator end() { return iterator(nullptr); }
- _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return const_iterator(nullptr); }
+ _LIBCPP_HIDE_FROM_ABI constexpr iterator end() { return iterator(nullptr); }
+ _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const { return const_iterator(nullptr); }
# endif
>From b61f90bc76c5d604655b034a664bf5c0b3452e10 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 15:19:26 +0300
Subject: [PATCH 18/25] [libcxx] use assert in optional.range.iteration.pass
test
---
.../utilities/optional/optional.range/iteration.pass.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
index 8ab1c099d30b5..5e5265d7cc86e 100644
--- a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
@@ -8,13 +8,12 @@
// UNSUPPORTED: std-at-least-c++26
-#include <iostream>
+#include <cassert>
#include <optional>
int main() {
std::optional<int> val = 2;
- for (const auto& elem : val) {
- std::cout << elem << std::endl;
- }
+ for (const auto& elem : val)
+ assert(elem == 2);
return 0;
}
\ No newline at end of file
>From 6993061ee65e60054fdd661faf668c8c7ea95454 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 15:33:14 +0300
Subject: [PATCH 19/25] [libcxx] use static_assert in
optional.range.satisfies_range_concept.pass test
---
.../utilities/optional/optional.range/iteration.pass.cpp | 2 +-
.../optional.range/satisfies_range_concept.pass.cpp | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
index 5e5265d7cc86e..a3c3af9d44adf 100644
--- a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
@@ -16,4 +16,4 @@ int main() {
for (const auto& elem : val)
assert(elem == 2);
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
index 96ba4c0903067..9b8a3712ac7dc 100644
--- a/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
@@ -8,12 +8,10 @@
// UNSUPPORTED: std-at-least-c++26
-#include <iostream>
#include <optional>
#include <ranges>
int main() {
- bool status = std::ranges::range<std::optional<int>>;
- std::cout << "std::ranges::range<std::optional<int>> is " << status << std::endl;
+ static_assert(std::ranges::range<std::optional<int>>, "std::ranges::range<std::optional<int>> is false");
return 0;
-}
\ No newline at end of file
+}
>From a3ef155d0594101e1a43018fdd59dd166abd0784 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 16:11:37 +0300
Subject: [PATCH 20/25] [libcxx] add additional operators to
__optional_iterator
---
libcxx/.clangd | 2 ++
libcxx/include/optional | 66 +++++++++++++++++++++++++++++++++++++----
2 files changed, 63 insertions(+), 5 deletions(-)
create mode 100644 libcxx/.clangd
diff --git a/libcxx/.clangd b/libcxx/.clangd
new file mode 100644
index 0000000000000..8a80936175292
--- /dev/null
+++ b/libcxx/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+ Add: [--std=c++2c]
\ No newline at end of file
diff --git a/libcxx/include/optional b/libcxx/include/optional
index a8a88a1614b07..65ef2022440fe 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -633,21 +633,77 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return *__ptr_; }
_LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { return *__ptr_; }
- _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator++() {
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator++() noexcept {
__ptr_ = nullptr;
return *this;
}
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator++(int) noexcept {
+ auto __t = *this;
+ __ptr_ = nullptr;
+ return __t;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator--() noexcept {
+ __ptr_ = nullptr;
+ return *this;
+ }
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator--(int) noexcept {
+ auto __t = *this;
+ __ptr_ = nullptr;
+ return __t;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator+=(difference_type __n) noexcept {
+ if (__n != 0)
+ __ptr_ = nullptr;
+ return *this;
+ }
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator-=(difference_type __n) noexcept {
+ if (__n != 0)
+ __ptr_ = nullptr;
+ return *this;
+ }
- _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator++(int) {
- __optional_iterator __tmp = *this;
- __ptr_ = nullptr;
- return __tmp;
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
+ operator+(__optional_iterator __i, difference_type __n) noexcept {
+ return (__n == 0 ? __i : __optional_iterator{});
+ }
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
+ operator+(difference_type __n, __optional_iterator __i) noexcept {
+ return __i + __n;
+ }
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
+ operator-(__optional_iterator __i, difference_type __n) noexcept {
+ return (__n == 0 ? __i : __optional_iterator{});
}
+ _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+ operator-(__optional_iterator __a, __optional_iterator __b) noexcept {
+ return (__a.__ptr_ == __b.__ptr_ ? 0 : (__a.__ptr_ ? 1 : -1));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](difference_type __n) const noexcept { return *(*this + __n); }
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const __optional_iterator& __other) const {
return __ptr_ == __other.__ptr_;
}
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+ operator<(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
+ return __a.__ptr_ < __b.__ptr_;
+ }
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+ operator>(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
+ return __a.__ptr_ > __b.__ptr_;
+ }
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+ operator<=(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
+ return __a.__ptr_ <= __b.__ptr_;
+ }
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+ operator>=(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
+ return __a.__ptr_ >= __b.__ptr_;
+ }
+
template <typename _Ut = _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr operator __optional_iterator<const _Tp>() const
requires(!std::is_const_v<_Ut>)
>From 6d4be2177cdcfdd39bba9af5d712d297fd891d63 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 16:12:49 +0300
Subject: [PATCH 21/25] [libcxx] remove .clangd
---
libcxx/.clangd | 2 --
1 file changed, 2 deletions(-)
delete mode 100644 libcxx/.clangd
diff --git a/libcxx/.clangd b/libcxx/.clangd
deleted file mode 100644
index 8a80936175292..0000000000000
--- a/libcxx/.clangd
+++ /dev/null
@@ -1,2 +0,0 @@
-CompileFlags:
- Add: [--std=c++2c]
\ No newline at end of file
>From 47ba8682e4e5f61b38abbeb4b845be230e3c31f9 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 16:32:47 +0300
Subject: [PATCH 22/25] [libcxx] add iterator_types.verify test to
optional.ranges
---
.../optional.range/iterator_types.verify.cpp | 28 +++++++++++++++++++
...cpp => satisfies_range_concept.verify.cpp} | 2 +-
2 files changed, 29 insertions(+), 1 deletion(-)
create mode 100644 libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
rename libcxx/test/std/utilities/optional/optional.range/{satisfies_range_concept.pass.cpp => satisfies_range_concept.verify.cpp} (81%)
diff --git a/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp b/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
new file mode 100644
index 0000000000000..c4e35aa727f5c
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: std-at-least-c++26
+
+#include <iterator>
+#include <optional>
+
+int main() {
+ using Iter = std::optional<int>::iterator;
+
+ std::iterator_traits<int> s;
+ static_assert(std::random_access_iterator<Iter>);
+ static_assert(std::contiguous_iterator<Iter>);
+
+ static_assert(std::is_same_v<typename std::iterator_traits<Iter>::value_type, int>);
+ static_assert(std::is_same_v<typename std::iterator_traits<Iter>::difference_type, std::ptrdiff_t>);
+ static_assert(std::is_same_v<typename std::iterator_traits<Iter>::pointer, int*>);
+ static_assert(std::is_same_v<typename std::iterator_traits<Iter>::reference, int&>);
+ static_assert(
+ std::is_same_v<typename std::iterator_traits<Iter>::iterator_category, std::random_access_iterator_tag>);
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.verify.cpp
similarity index 81%
rename from libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
rename to libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.verify.cpp
index 9b8a3712ac7dc..907e482a81115 100644
--- a/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/satisfies_range_concept.verify.cpp
@@ -12,6 +12,6 @@
#include <ranges>
int main() {
- static_assert(std::ranges::range<std::optional<int>>, "std::ranges::range<std::optional<int>> is false");
+ static_assert(std::ranges::range<std::optional<int>>);
return 0;
}
>From 3f69edaef08c0c860b348d748f3667b3f72d777a Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 16:37:02 +0300
Subject: [PATCH 23/25] [libcxx] add missing new character line at EOF
---
.../utilities/optional/optional.range/iterator_types.verify.cpp | 2 +-
.../utilities/optional/optional.range/runtime_error.fail.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp b/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
index c4e35aa727f5c..09d3c9d0274d7 100644
--- a/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/iterator_types.verify.cpp
@@ -25,4 +25,4 @@ int main() {
static_assert(
std::is_same_v<typename std::iterator_traits<Iter>::iterator_category, std::random_access_iterator_tag>);
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
index fa74c2b477efd..c0ed1a4b62426 100644
--- a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
@@ -16,4 +16,4 @@ int main() {
auto end = val.end();
TEST_DOES_NOT_THROW(*end);
return 0;
-}
\ No newline at end of file
+}
>From ef8af0aa35f6a463da71abe8c0dc4b0cec531d4f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 16:49:28 +0300
Subject: [PATCH 24/25] [libcxx] change optional.range.iteration.pass test to
constant eveluated
---
libcxx/include/optional | 8 --------
.../optional/optional.range/iteration.pass.cpp | 12 +++++++++---
...ntime_error.fail.cpp => runtime_error.verify.cpp} | 0
3 files changed, 9 insertions(+), 11 deletions(-)
rename libcxx/test/std/utilities/optional/optional.range/{runtime_error.fail.cpp => runtime_error.verify.cpp} (100%)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 65ef2022440fe..ae65c7c1be7c2 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -200,7 +200,6 @@ namespace std {
# include <__concepts/invocable.h>
# include <__config>
# include <__exception/exception.h>
-# include <__format/format_context.h>
# include <__format/range_default_formatter.h>
# include <__functional/hash.h>
# include <__functional/invoke.h>
@@ -581,13 +580,6 @@ using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
template <class _Tp>
class optional;
-# if _LIBCPP_STD_VER >= 26
-
-template <typename _Tp>
-class __optional_iterator;
-
-# endif // _LIBCPP_STD_VER >= 26
-
# if _LIBCPP_STD_VER >= 20
template <class _Tp>
diff --git a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
index a3c3af9d44adf..ff9b0602c2a5e 100644
--- a/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.range/iteration.pass.cpp
@@ -11,9 +11,15 @@
#include <cassert>
#include <optional>
-int main() {
- std::optional<int> val = 2;
+constexpr bool test() {
+ constexpr std::optional<int> val = 2;
for (const auto& elem : val)
- assert(elem == 2);
+ if (elem != 2)
+ return false;
+ return true;
+}
+
+int main() {
+ static_assert(test());
return 0;
}
diff --git a/libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp b/libcxx/test/std/utilities/optional/optional.range/runtime_error.verify.cpp
similarity index 100%
rename from libcxx/test/std/utilities/optional/optional.range/runtime_error.fail.cpp
rename to libcxx/test/std/utilities/optional/optional.range/runtime_error.verify.cpp
>From 04b551120779bdd61eff0b0af69b40b3c51bd8ec Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 1 Jul 2025 17:01:23 +0300
Subject: [PATCH 25/25] [libcxx] use __wrap_iter in __optional_iterator
---
libcxx/.clangd | 2 ++
libcxx/include/optional | 73 ++++++++++++++++++++++-------------------
2 files changed, 42 insertions(+), 33 deletions(-)
create mode 100644 libcxx/.clangd
diff --git a/libcxx/.clangd b/libcxx/.clangd
new file mode 100644
index 0000000000000..8a80936175292
--- /dev/null
+++ b/libcxx/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+ Add: [--std=c++2c]
\ No newline at end of file
diff --git a/libcxx/include/optional b/libcxx/include/optional
index ae65c7c1be7c2..e2e008c2fffb1 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -205,6 +205,7 @@ namespace std {
# include <__functional/invoke.h>
# include <__functional/unary_function.h>
# include <__fwd/functional.h>
+# include <__iterator/wrap_iter.h>
# include <__memory/addressof.h>
# include <__memory/construct_at.h>
# include <__tuple/sfinae_helpers.h>
@@ -602,63 +603,65 @@ constexpr auto format_kind<optional<_T>> = range_format::disabled;
template <typename _Tp>
class __optional_iterator {
+ using _Base = __wrap_iter<_Tp*>;
+ _Base __it_;
+
public:
using value_type = _Tp;
- using difference_type = std::ptrdiff_t;
- using pointer = _Tp*;
- using reference = _Tp&;
+ using difference_type = typename _Base::difference_type;
+ using pointer = typename _Base::pointer;
+ using reference = typename _Base::reference;
using iterator_category = random_access_iterator_tag;
using iterator_concept = contiguous_iterator_tag;
private:
- pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_iterator(pointer __ptr) : __ptr_(__ptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_iterator(_Base __it) noexcept : __it_(__it) {}
_LIBCPP_HIDE_FROM_ABI friend class optional<std::remove_const_t<_Tp>>;
_LIBCPP_HIDE_FROM_ABI friend class optional<const _Tp>;
public:
- _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator() : __ptr_(nullptr) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator() : __it_(_Base()) {}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator(const __optional_iterator&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator=(const __optional_iterator&) = default;
- _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return *__ptr_; }
- _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { return *__ptr_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return *__it_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { return *__it_.operator->(); }
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator++() noexcept {
- __ptr_ = nullptr;
+ __it_ = _Base();
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator++(int) noexcept {
- auto __t = *this;
- __ptr_ = nullptr;
- return __t;
+ auto __tmp = *this;
+ __it_ = _Base();
+ return __tmp;
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator--() noexcept {
- __ptr_ = nullptr;
+ __it_ = _Base();
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator operator--(int) noexcept {
- auto __t = *this;
- __ptr_ = nullptr;
- return __t;
+ auto __tmp = *this;
+ __it_ = _Base();
+ return __tmp;
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator+=(difference_type __n) noexcept {
if (__n != 0)
- __ptr_ = nullptr;
+ __it_ = _Base();
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_iterator& operator-=(difference_type __n) noexcept {
if (__n != 0)
- __ptr_ = nullptr;
+ __it_ = _Base();
return *this;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
operator+(__optional_iterator __i, difference_type __n) noexcept {
- return (__n == 0 ? __i : __optional_iterator{});
+ return (__n == 0 ? __i : __optional_iterator(_Base()));
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
operator+(difference_type __n, __optional_iterator __i) noexcept {
@@ -666,41 +669,41 @@ public:
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __optional_iterator
operator-(__optional_iterator __i, difference_type __n) noexcept {
- return (__n == 0 ? __i : __optional_iterator{});
+ return (__n == 0 ? __i : __optional_iterator(_Base()));
}
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
operator-(__optional_iterator __a, __optional_iterator __b) noexcept {
- return (__a.__ptr_ == __b.__ptr_ ? 0 : (__a.__ptr_ ? 1 : -1));
+ return (__a.__it_ == __b.__it_ ? 0 : (__a.__it_ ? 1 : -1));
}
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](difference_type __n) const noexcept { return *(*this + __n); }
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const __optional_iterator& __other) const {
- return __ptr_ == __other.__ptr_;
+ return __it_ == __other.__it_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator<(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
- return __a.__ptr_ < __b.__ptr_;
+ return __a.__it_ < __b.__it_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator>(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
- return __a.__ptr_ > __b.__ptr_;
+ return __a.__it_ > __b.__it_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator<=(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
- return __a.__ptr_ <= __b.__ptr_;
+ return __a.__it_ <= __b.__it_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator>=(const __optional_iterator& __a, const __optional_iterator& __b) noexcept {
- return __a.__ptr_ >= __b.__ptr_;
+ return __a.__it_ >= __b.__it_;
}
template <typename _Ut = _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr operator __optional_iterator<const _Tp>() const
requires(!std::is_const_v<_Ut>)
{
- return __optional_iterator<const _Tp>(static_cast<const _Tp*>(__ptr_));
+ return __optional_iterator<const _Tp>(__wrap_iter<const _Tp*>{__it_.base()});
}
};
@@ -1116,17 +1119,21 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr iterator begin() {
if (!this->has_value())
- return this->end();
- return iterator(static_cast<_Tp*>(this->__get()));
+ return end();
+ return iterator(__wrap_iter(static_cast<_Tp*>(this->__get())));
}
+
_LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const {
if (!this->has_value())
- return this->end();
- return const_iterator(static_cast<_Tp*>(this->value()));
+ return end();
+ return const_iterator(__wrap_iter(static_cast<const _Tp*>(this->__get())));
}
- _LIBCPP_HIDE_FROM_ABI constexpr iterator end() { return iterator(nullptr); }
- _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const { return const_iterator(nullptr); }
+ _LIBCPP_HIDE_FROM_ABI constexpr iterator end() { return iterator(__wrap_iter(static_cast<_Tp*>(nullptr))); }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const {
+ return const_iterator(__wrap_iter(static_cast<const _Tp*>(nullptr)));
+ }
# endif
More information about the libcxx-commits
mailing list