Skip to content

[libc++] Implement P3168R2: Give optional range support #149441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_not_fn`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_optional_range_support`` *unimplemented*
``__cpp_lib_optional_range_support`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` ``202311L``
---------------------------------------------------------- -----------------
Expand Down
3 changes: 3 additions & 0 deletions libcxx/docs/ReleaseNotes/22.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ What's New in Libc++ 22.0.0?
==============================

Implemented Papers

- P3168R2: Give ``std::optional`` Range Support (`Github <https://github.com/llvm/llvm-project/issues/105430>`__)

------------------


Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20",""
"`P2997R1 <https://wg21.link/P2997R1>`__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete|","19","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)"
"`P2389R2 <https://wg21.link/P2389R2>`__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19",""
"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","",""
"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","|Complete|","22",""
"`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","",""
"`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20",""
"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","","",""
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/__iterator/wrap_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class __wrap_iter {
friend class span;
template <class _Tp, size_t _Size>
friend struct array;
template <class _Tp>
friend class optional;
Comment on lines +120 to +121
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should guard this declaration with _LIBCPP_STD_VER >= 26 (or at least _LIBCPP_STD_VER >= 17). Although the declaration of span wasn't guarded previously.

};

template <class _Iter1>
Expand Down
49 changes: 49 additions & 0 deletions libcxx/include/optional
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ namespace std {
template <class T>
class optional;

template<class T>
constexpr bool ranges::enable_view<optional<T>> = true;
template<class T>
constexpr auto format_kind<optional<T>> = range_format::disabled;

template<class T>
concept is-derived-from-optional = requires(const T& t) { // exposition only
[]<class U>(const optional<U>&){ }(t);
Expand Down Expand Up @@ -102,6 +107,8 @@ namespace std {
class optional {
public:
using value_type = T;
using iterator = implementation-defined; // see [optional.iterators]
using const_iterator = implementation-defined; // see [optional.iterators]

// [optional.ctor], constructors
constexpr optional() noexcept;
Expand Down Expand Up @@ -135,6 +142,12 @@ namespace std {
// [optional.swap], swap
void swap(optional &) noexcept(see below ); // constexpr in C++20

// [optional.iterators], iterator support
constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;

// [optional.observe], observers
constexpr T const *operator->() const noexcept;
constexpr T *operator->() noexcept;
Expand Down Expand Up @@ -186,13 +199,16 @@ namespace std {
# include <__compare/three_way_comparable.h>
# include <__concepts/invocable.h>
# include <__config>
# include <__cstddef/ptrdiff_t.h>
# include <__exception/exception.h>
# include <__functional/hash.h>
# 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 <__ranges/enable_view.h>
# include <__tuple/sfinae_helpers.h>
# include <__type_traits/add_pointer.h>
# include <__type_traits/conditional.h>
Expand Down Expand Up @@ -233,6 +249,10 @@ namespace std {
# include <initializer_list>
# include <version>

# if _LIBCPP_STD_VER >= 26
# include <__format/range_format.h>
# endif

// standard-mandated includes

// [optional.syn]
Expand Down Expand Up @@ -567,6 +587,14 @@ using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
template <class _Tp>
class optional;

# if _LIBCPP_STD_VER >= 26
template <class _Tp>
constexpr bool ranges::enable_view<optional<_Tp>> = true;

template <class _Tp>
constexpr range_format format_kind<optional<_Tp>> = range_format::disabled;
# endif

# if _LIBCPP_STD_VER >= 20

template <class _Tp>
Expand All @@ -586,8 +614,17 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
private __optional_sfinae_assign_base_t<_Tp> {
using __base _LIBCPP_NODEBUG = __optional_move_assign_base<_Tp>;

# if _LIBCPP_STD_VER >= 26
using pointer = std::add_pointer_t<std::remove_cvref_t<_Tp>>;
using const_pointer = std::add_pointer_t<const std::remove_cvref_t<_Tp>>;
# endif

public:
using value_type = _Tp;
# if _LIBCPP_STD_VER >= 26
using iterator = __wrap_iter<pointer>;
using const_iterator = __wrap_iter<const_pointer>;
# endif

using __trivially_relocatable _LIBCPP_NODEBUG =
conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
Expand Down Expand Up @@ -792,6 +829,18 @@ public:
}
}

# if _LIBCPP_STD_VER >= 26
// [optional.iterators], iterator support
_LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept { return iterator(std::addressof(this->__get())); }

_LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
return const_iterator(std::addressof(this->__get()));
}

_LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept { return begin() + this->has_value(); }
_LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { return begin() + this->has_value(); }
# endif

_LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
return std::addressof(this->__get());
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,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
Expand Down
11 changes: 10 additions & 1 deletion libcxx/modules/std/optional.inc
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@
export namespace std {
// [optional.optional], class template optional
using std::optional;

#if _LIBCPP_STD_VER >= 26
// [optional.iterators], iterator support
namespace ranges {
using std::ranges::enable_view;
}
#endif
// [optional.nullopt], no-value state indicator
using std::nullopt;
using std::nullopt_t;

// [optional.bad.access], class bad_optional_access
using std::bad_optional_access;

#if _LIBCPP_STD_VER >= 26
using std::format_kind;
#endif

// [optional.relops], relational operators
using std::operator==;
using std::operator!=;
Expand Down
47 changes: 47 additions & 0 deletions libcxx/test/libcxx/transitive_includes/cxx26.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ algorithm cctype
algorithm climits
algorithm compare
algorithm cstdint
algorithm cstdio
algorithm cstring
algorithm ctime
algorithm cwchar
Expand All @@ -11,6 +12,8 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
algorithm stdexcept
algorithm string_view
algorithm tuple
algorithm version
any cstdint
Expand Down Expand Up @@ -330,26 +333,32 @@ flat_map cctype
flat_map climits
flat_map compare
flat_map cstdint
flat_map cstdio
flat_map cstring
flat_map cwchar
flat_map cwctype
flat_map initializer_list
flat_map iosfwd
flat_map limits
flat_map optional
flat_map stdexcept
flat_map string_view
flat_map tuple
flat_map version
flat_set cctype
flat_set climits
flat_set compare
flat_set cstdint
flat_set cstdio
flat_set cstring
flat_set cwchar
flat_set cwctype
flat_set initializer_list
flat_set iosfwd
flat_set limits
flat_set optional
flat_set stdexcept
flat_set string_view
flat_set tuple
flat_set version
format array
Expand Down Expand Up @@ -417,13 +426,16 @@ functional array
functional cctype
functional compare
functional cstdint
functional cstdio
functional cstring
functional cwchar
functional cwctype
functional initializer_list
functional iosfwd
functional limits
functional optional
functional stdexcept
functional string_view
functional tuple
functional typeinfo
functional unordered_map
Expand Down Expand Up @@ -623,13 +635,16 @@ locale version
map cctype
map compare
map cstdint
map cstdio
map cstring
map cwchar
map cwctype
map initializer_list
map iosfwd
map limits
map optional
map stdexcept
map string_view
map tuple
map version
mdspan array
Expand Down Expand Up @@ -673,22 +688,36 @@ mutex typeinfo
mutex version
new version
numbers version
numeric cctype
numeric climits
numeric compare
numeric cstdint
numeric cstdio
numeric cstring
numeric ctime
numeric cwchar
numeric cwctype
numeric initializer_list
numeric iosfwd
numeric limits
numeric optional
numeric ratio
numeric stdexcept
numeric string_view
numeric tuple
numeric version
optional cctype
optional compare
optional cstdint
optional cstdio
optional cstring
optional cwchar
optional cwctype
optional initializer_list
optional iosfwd
optional limits
optional stdexcept
optional string_view
optional version
ostream array
ostream bitset
Expand Down Expand Up @@ -806,6 +835,7 @@ ranges limits
ranges optional
ranges span
ranges stdexcept
ranges string_view
ranges tuple
ranges variant
ranges version
Expand Down Expand Up @@ -851,12 +881,16 @@ semaphore version
set cctype
set compare
set cstdint
set cstdio
set cstring
set cwchar
set cwctype
set initializer_list
set iosfwd
set limits
set optional
set stdexcept
set string_view
set tuple
set version
shared_mutex cerrno
Expand Down Expand Up @@ -1091,21 +1125,34 @@ typeindex typeinfo
typeindex version
typeinfo cstdint
typeinfo version
unordered_map cctype
unordered_map compare
unordered_map cstdint
unordered_map cstdio
unordered_map cstring
unordered_map cwchar
unordered_map cwctype
unordered_map initializer_list
unordered_map iosfwd
unordered_map limits
unordered_map optional
unordered_map stdexcept
unordered_map string_view
unordered_map tuple
unordered_map version
unordered_set cctype
unordered_set compare
unordered_set cstdint
unordered_set cstdio
unordered_set cstring
unordered_set cwchar
unordered_set cwctype
unordered_set initializer_list
unordered_set iosfwd
unordered_set limits
unordered_set optional
unordered_set stdexcept
unordered_set string_view
unordered_set tuple
unordered_set version
utility compare
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading