diff --git a/include/fast_io_dsal/impl/list.h b/include/fast_io_dsal/impl/list.h index d395e3866..ed76355cf 100644 --- a/include/fast_io_dsal/impl/list.h +++ b/include/fast_io_dsal/impl/list.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace fast_io { @@ -22,15 +24,73 @@ struct list_node T element; }; -template +template +class list_const_iterator +{ +public: + using value_type = T; + using pointer = value_type const *; + using const_pointer = value_type const *; + + using reference = value_type const &; + using const_reference = value_type const &; + + using size_type = ::std::size_t; + using difference_type = ::std::ptrdiff_t; + void const *iter{}; + + inline constexpr list_const_iterator &operator++() noexcept + { + iter = static_cast(iter)->next; + return *this; + } + + inline constexpr list_const_iterator &operator--() noexcept + { + iter = static_cast(iter)->prev; + return *this; + } + + inline constexpr list_const_iterator operator++(int) noexcept + { + auto temp(*this); + ++*this; + return temp; + } + + inline constexpr list_const_iterator operator--(int) noexcept + { + auto temp(*this); + --*this; + return temp; + } + + inline constexpr const_reference operator*() const noexcept + { + return static_cast const *>(iter)->element; + } + + inline constexpr const_pointer operator->() const noexcept + { + return __builtin_addressof(static_cast const *>(iter)->element); + } +}; + +template +constexpr bool is_list_const_iterator_ = false; + +template +constexpr bool is_list_const_iterator_<::fast_io::containers::details::list_const_iterator> = true; + +template class list_iterator { public: using value_type = T; - using pointer = ::std::conditional_t; + using pointer = value_type *; using const_pointer = value_type const *; - using reference = ::std::conditional_t; + using reference = value_type &; using const_reference = value_type const &; using size_type = ::std::size_t; @@ -73,23 +133,25 @@ class list_iterator return __builtin_addressof(static_cast *>(iter)->element); } - inline constexpr operator list_iterator() const noexcept - requires(!isconst) + inline constexpr operator list_const_iterator() const noexcept { return {this->iter}; } }; -template -inline constexpr bool operator==(list_iterator a, list_iterator b) noexcept -{ - return a.iter == b.iter; -} +template +constexpr bool is_list_iterator_ = false; + +template +constexpr bool is_list_iterator_<::fast_io::containers::details::list_iterator> = true; -template -inline constexpr bool operator!=(list_iterator a, list_iterator b) noexcept +template +concept is_list_forward_iterator = ::fast_io::containers::details::is_list_iterator_<::std::remove_cvref_t> || ::fast_io::containers::details::is_list_const_iterator_<::std::remove_cvref_t>; + +template +inline constexpr bool operator==(T &&a, U &&b) noexcept { - return a.iter != b.iter; + return a.iter == b.iter; } template @@ -494,8 +556,8 @@ class list using size_type = ::std::size_t; using difference_type = ::std::ptrdiff_t; - using iterator = ::fast_io::containers::details::list_iterator; - using const_iterator = ::fast_io::containers::details::list_iterator; + using iterator = ::fast_io::containers::details::list_iterator; + using const_iterator = ::fast_io::containers::details::list_const_iterator; using reverse_iterator = ::std::reverse_iterator; using const_reverse_iterator = ::std::reverse_iterator; diff --git a/tests/0026.container/0002.list/list_iter.cc b/tests/0026.container/0002.list/list_iter.cc new file mode 100644 index 000000000..0fecb0d06 --- /dev/null +++ b/tests/0026.container/0002.list/list_iter.cc @@ -0,0 +1,174 @@ +#include + +struct X +{ + int a; +}; + +void test_iter() +{ + ::fast_io::list l{X{1}, X{2}, X{3}}; + + auto iter = l.begin(); + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 1 || value2 != 1 || value3.a != 1) + { + ::fast_io::fast_terminate(); + } + } + + ++iter; + + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 3 || value2 != 3 || value3.a != 3) + { + ::fast_io::fast_terminate(); + } + } + + if (iter != l.end()) + { + ::fast_io::fast_terminate(); + } +} + +void test_iter2() +{ + ::fast_io::list l{X{1}, X{2}, X{3}}; + + for (auto &&v : l) + { + if (v.a != 1 && v.a != 2 && v.a != 3) + { + ::fast_io::fast_terminate(); + } + } +} + +void test_const_iter() +{ + ::fast_io::list const l{X{1}, X{2}, X{3}}; + + auto iter = l.begin(); + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 1 || value2 != 1 || value3.a != 1) + { + ::fast_io::fast_terminate(); + } + } + + ++iter; + + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 3 || value2 != 3 || value3.a != 3) + { + ::fast_io::fast_terminate(); + } + } + + if (iter != l.end()) + { + ::fast_io::fast_terminate(); + } +} + +void test_const_iter2() +{ + ::fast_io::list const l{X{1}, X{2}, X{3}}; + + for (auto &&v : l) + { + if (v.a != 1 && v.a != 2 && v.a != 3) + { + ::fast_io::fast_terminate(); + } + } +} + +void test_reverse_iter() +{ + ::fast_io::list l{X{1}, X{2}, X{3}}; + auto iter = l.rbegin(); + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 3 || value2 != 3 || value3.a != 3) + { + ::fast_io::fast_terminate(); + } + } + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 2 || value2 != 2 || value3.a != 2) + { + ::fast_io::fast_terminate(); + } + } + ++iter; + if (iter != l.rend()) + { + ::fast_io::fast_terminate(); + } +} + +void test_reverse_const_iter() +{ + ::fast_io::list const l{X{1}, X{2}, X{3}}; + auto iter = l.rbegin(); + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 3 || value2 != 3 || value3.a != 3) + { + ::fast_io::fast_terminate(); + } + } + { + auto &&value = *iter; + auto &&value2 = iter->a; + auto value3 = *iter++; + + if (value.a != 2 || value2 != 2 || value3.a != 2) + { + ::fast_io::fast_terminate(); + } + } + ++iter; + if (iter != l.rend()) + { + ::fast_io::fast_terminate(); + } +} + +int main() +{ + ::test_iter(); + ::test_iter2(); + ::test_const_iter(); + ::test_const_iter2(); + ::test_reverse_iter(); + ::test_reverse_const_iter(); +}