Skip to content
Closed
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
92 changes: 77 additions & 15 deletions include/fast_io_dsal/impl/list.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <type_traits>

namespace fast_io
{

Expand All @@ -22,15 +24,73 @@ struct list_node
T element;
};

template <typename T, bool isconst>
template <typename T>
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<list_node_common const *>(iter)->next;
return *this;
}

inline constexpr list_const_iterator &operator--() noexcept
{
iter = static_cast<list_node_common const *>(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<list_node<T> const *>(iter)->element;
}

inline constexpr const_pointer operator->() const noexcept
{
return __builtin_addressof(static_cast<list_node<T> const *>(iter)->element);
}
};

template <typename T>
constexpr bool is_list_const_iterator_ = false;

template <typename T>
constexpr bool is_list_const_iterator_<::fast_io::containers::details::list_const_iterator<T>> = true;

template <typename T>
class list_iterator
{
public:
using value_type = T;
using pointer = ::std::conditional_t<isconst, value_type const *, value_type *>;
using pointer = value_type *;
using const_pointer = value_type const *;

using reference = ::std::conditional_t<isconst, value_type const &, value_type &>;
using reference = value_type &;
using const_reference = value_type const &;

using size_type = ::std::size_t;
Expand Down Expand Up @@ -73,23 +133,25 @@ class list_iterator
return __builtin_addressof(static_cast<list_node<T> *>(iter)->element);
}

inline constexpr operator list_iterator<T, true>() const noexcept
requires(!isconst)
inline constexpr operator list_const_iterator<T>() const noexcept
{
return {this->iter};
}
};

template <typename T, bool isconst1, bool isconst2>
inline constexpr bool operator==(list_iterator<T, isconst1> a, list_iterator<T, isconst2> b) noexcept
{
return a.iter == b.iter;
}
template <typename T>
constexpr bool is_list_iterator_ = false;

template <typename T>
constexpr bool is_list_iterator_<::fast_io::containers::details::list_iterator<T>> = true;

template <typename T, bool isconst1, bool isconst2>
inline constexpr bool operator!=(list_iterator<T, isconst1> a, list_iterator<T, isconst2> b) noexcept
template <typename T>
concept is_list_forward_iterator = ::fast_io::containers::details::is_list_iterator_<::std::remove_cvref_t<T>> || ::fast_io::containers::details::is_list_const_iterator_<::std::remove_cvref_t<T>>;

template <is_list_forward_iterator T, is_list_forward_iterator U>
inline constexpr bool operator==(T &&a, U &&b) noexcept
{
return a.iter != b.iter;
return a.iter == b.iter;
}

template <typename allocator>
Expand Down Expand Up @@ -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<T, false>;
using const_iterator = ::fast_io::containers::details::list_iterator<T, true>;
using iterator = ::fast_io::containers::details::list_iterator<T>;
using const_iterator = ::fast_io::containers::details::list_const_iterator<T>;

using reverse_iterator = ::std::reverse_iterator<iterator>;
using const_reverse_iterator = ::std::reverse_iterator<const_iterator>;
Expand Down
174 changes: 174 additions & 0 deletions tests/0026.container/0002.list/list_iter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#include <fast_io_dsal/list.h>

struct X
{
int a;
};

void test_iter()
{
::fast_io::list<X> 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<X> 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<X> 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<X> 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<X> 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<X> 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();
}
Loading