From 8c3e33262996ab78d287e27e30762590f07750ea Mon Sep 17 00:00:00 2001 From: Yong Gyu Lee Date: Sun, 20 Oct 2024 02:34:20 +0900 Subject: [PATCH 1/2] Create pointer_iterator.h --- include/preview/__iterator/pointer_iterator.h | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 include/preview/__iterator/pointer_iterator.h diff --git a/include/preview/__iterator/pointer_iterator.h b/include/preview/__iterator/pointer_iterator.h new file mode 100644 index 0000000..b9e66fb --- /dev/null +++ b/include/preview/__iterator/pointer_iterator.h @@ -0,0 +1,88 @@ +// +// Created by yonggyulee on 2024. 10. 20. +// + +#ifndef PREVIEW_ITERATOR_POINTER_ITERATOR_H_ +#define PREVIEW_ITERATOR_POINTER_ITERATOR_H_ + +#include +#include + +#include "preview/__iterator/detail/contiguous_iterator_tag.h" +#include "preview/__iterator/iterator_tag.h" + +namespace preview { +namespace detail { + +template +class pointer_iterator { + public: + using difference_type = std::ptrdiff_t; + using value_type = std::remove_cv_t; + using pointer = T*; + using reference = T&; + using iterator_category = std::random_access_iterator_tag; + using iterator_concept = contiguous_iterator_tag; + + pointer_iterator() = default; + + constexpr pointer_iterator(pointer p) + : ptr_(p) {} + + constexpr reference operator*() const noexcept { return *ptr_; } + constexpr pointer operator->() const noexcept { return ptr_; } + + constexpr reference operator[](difference_type n) const noexcept { + return ptr_[n]; + } + + constexpr pointer_iterator& operator++() noexcept { + ++ptr_; + return *this; + } + constexpr pointer_iterator operator++(int) noexcept { + pointer_iterator temp{*this}; + ++*this; + return temp; + } + + constexpr pointer_iterator& operator--() noexcept { + --ptr_; + return *this; + } + constexpr pointer_iterator operator--(int) noexcept { + pointer_iterator temp{*this}; + --*this; + return temp; + } + + constexpr pointer_iterator& operator+=(difference_type n) const noexcept { + ptr_ += n; + return *this; + } + + constexpr pointer_iterator& operator-=(difference_type n) const noexcept { + ptr_ -= n; + return *this; + } + + friend constexpr bool operator==(pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ == y.ptr_; } + friend constexpr bool operator!=(pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ != y.ptr_; } + friend constexpr bool operator< (pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ < y.ptr_; } + friend constexpr bool operator<=(pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ <= y.ptr_; } + friend constexpr bool operator> (pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ > y.ptr_; } + friend constexpr bool operator>=(pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ >= y.ptr_; } + + friend constexpr pointer_iterator operator+(pointer_iterator i, difference_type n) noexcept { return pointer_iterator{i.ptr_ + n}; } + friend constexpr pointer_iterator operator+(difference_type n, pointer_iterator i) noexcept { return pointer_iterator{i.ptr_ + n}; } + friend constexpr pointer_iterator operator-(pointer_iterator i, difference_type n) noexcept { return pointer_iterator{i.ptr_ - n}; } + friend constexpr difference_type operator-(pointer_iterator x, pointer_iterator y) noexcept { return x.ptr_ - y.ptr_; } + + private: + pointer ptr_ = nullptr; +}; + +} // namespace detail +} // namespace preview + +#endif // PREVIEW_ITERATOR_POINTER_ITERATOR_H_ From aa54d4c2909a547e6fadf17a29da104def06a2d4 Mon Sep 17 00:00:00 2001 From: Yong Gyu Lee Date: Sun, 20 Oct 2024 02:34:31 +0900 Subject: [PATCH 2/2] Add ranges support to optional --- README.md | 20 +++++++++-------- include/preview/__optional/optional.h | 31 ++++++++++++++++++++++++++- test/optional/optional_test.cc | 21 ++++++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 92d72ea..2139dd6 100644 --- a/README.md +++ b/README.md @@ -901,19 +901,21 @@ Description #### `` - | | Introduced | Revision | - |-----------------------|-------------|-----------------------| - | `optional` | ![][c17ok] | ![][c23ok] ![][c26no] | - | `bad_optional_access` | ![][c17ok] | | - | `std::hash` | ![][c17ok] | | - | `nullopt` | ![][c17ok]* | | - | `nullopt_t` | ![][c17ok]* | | - | `swap(optional)` | ![][c17ok] | | - | `make_optional` | ![][c17ok] | | + | | Introduced | Revision | + |-----------------------|-------------|------------------------| + | `optional` | ![][c17ok] | ![][c23ok] ![][c26ok]* | + | `bad_optional_access` | ![][c17ok] | | + | `std::hash` | ![][c17ok] | | + | `nullopt` | ![][c17ok]* | | + | `nullopt_t` | ![][c17ok]* | | + | `swap(optional)` | ![][c17ok] | | + | `make_optional` | ![][c17ok] | | * Notes * `nullopt`, `nullopt_t` * `std::nullopt` is used if available, `preview::nullopt` otherwise. + * C++26 + * [P3168 (R2)](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3168r2.html) #### `` diff --git a/include/preview/__optional/optional.h b/include/preview/__optional/optional.h index 5e34b63..90a4d84 100644 --- a/include/preview/__optional/optional.h +++ b/include/preview/__optional/optional.h @@ -14,12 +14,15 @@ # include "preview/__concepts/invocable.h" # include "preview/__concepts/move_constructible.h" # include "preview/__functional/invoke.h" +# include "preview/__iterator/basic_const_iterator.h" +# include "preview/__iterator/pointer_iterator.h" # include "preview/__memory/addressof.h" # include "preview/__memory/construct_at.h" # include "preview/__memory/destroy_at.h" # include "preview/__optional/bad_optional_access.h" # include "preview/__optional/nullopt_t.h" # include "preview/__optional/swap.h" +# include "preview/__ranges/enable_view.h" # include "preview/__type_traits/detail/control_special.h" # include "preview/__type_traits/is_swappable.h" # include "preview/__type_traits/is_invocable.h" @@ -249,7 +252,9 @@ class optional : private detail::optional_control_smf { using base::base; public: - using value_type = T; + using value_type = T; + using iterator = detail::pointer_iterator; + using const_iterator = detail::pointer_iterator; static_assert(!std::is_reference::value, "preview::optional : T must not be a reference type"); @@ -600,6 +605,20 @@ class optional : private detail::optional_control_smf { this->construct_with(ilist, std::forward(args)...); return **this; } + + constexpr iterator begin() noexcept { + return iterator{has_value() ? preview::addressof(**this) : nullptr}; + } + constexpr const_iterator begin() const noexcept { + return const_iterator{has_value() ? preview::addressof(**this) : nullptr}; + } + + constexpr iterator end() noexcept { + return begin() + has_value(); + } + constexpr const_iterator end() const noexcept { + return begin() + has_value(); + } }; # if PREVIEW_CXX_VERSION >= 17 @@ -808,6 +827,16 @@ constexpr inline bool operator>=(const T& value, const optional& opt) { return bool(opt) ? value >= *opt : true; } + +// ranges support +namespace ranges { + +template +struct enable_view> : std::true_type {}; + +// TODO: Specialize format_kind + +} // namespace ranges } // namespace preview # endif // PREVIEW_OPTIONAL_OPTIONAL_H_ diff --git a/test/optional/optional_test.cc b/test/optional/optional_test.cc index a794888..fb0b7ea 100644 --- a/test/optional/optional_test.cc +++ b/test/optional/optional_test.cc @@ -371,3 +371,24 @@ TEST(VERSIONED(optional), copy_over_move) { std::swap(op1, op2); // copy is selected for non-movable object EXPECT_EQ(NoMove::copied, 2); } + +TEST(VERSIONED(optional), ranges) { + preview::optional o; + using I = decltype(o)::iterator; + using CI = decltype(o)::const_iterator; + + EXPECT_TRUE_TYPE(preview::contiguous_iterator); + EXPECT_TRUE_TYPE(preview::ranges::view); + EXPECT_EQ(o.begin(), o.begin()); + EXPECT_EQ(o.begin(), o.end()); + EXPECT_EQ(o.end(), o.end()); + EXPECT_EQ(preview::ranges::size(o), 0); + + o = 100; + EXPECT_EQ(o.begin(), o.begin()); + EXPECT_NE(o.begin(), o.end()); + EXPECT_EQ(o.end(), o.end()); + EXPECT_EQ(o.begin() + 1, o.end()); + EXPECT_EQ(o.begin(), o.end() - 1); + EXPECT_EQ(preview::ranges::size(o), 1); +}