:github_url: https://github.com/svenevs/exhale-companion .. _program_listing_file_ckpttncpp_dllist.hpp: Program Listing for File dllist.hpp =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``ckpttncpp/dllist.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include // #include #include // import std::move() // Forward declaration for begin() end() template class dll_iterator; #pragma pack(push, 1) template class dllink { friend dll_iterator; private: dllink* next {this}; dllink* prev {this}; public: T data {}; // Int key{}; /*!< key */ constexpr explicit dllink(T data) noexcept : data {std::move(data)} { static_assert(sizeof(dllink) <= 24, "keep this class small"); } constexpr dllink() = default; ~dllink() = default; dllink(const dllink&) = delete; // don't copy constexpr auto operator=(const dllink&) -> dllink& = delete; // don't assign constexpr dllink(dllink&&) noexcept = default; constexpr auto operator=(dllink&&) noexcept -> dllink& = default; // don't assign constexpr auto lock() noexcept -> void { this->next = nullptr; } [[nodiscard]] constexpr auto is_locked() const noexcept -> bool { return this->next == nullptr; } [[nodiscard]] constexpr auto is_empty() const noexcept -> bool { return this->next == this; } constexpr auto clear() noexcept -> void { this->next = this->prev = this; } constexpr auto detach() noexcept -> void { assert(!this->is_locked()); const auto n = this->next; const auto p = this->prev; p->next = n; n->prev = p; } constexpr auto appendleft(dllink& node) noexcept -> void { node.next = this->next; this->next->prev = &node; this->next = &node; node.prev = this; } constexpr auto append(dllink& node) noexcept -> void { node.prev = this->prev; this->prev->next = &node; this->prev = &node; node.next = this; } constexpr auto popleft() noexcept -> dllink& { auto res = this->next; this->next = res->next; this->next->prev = this; return *res; } constexpr auto pop() noexcept -> dllink& { auto res = this->prev; this->prev = res->prev; this->prev->next = this; return *res; } // For iterator constexpr auto begin() noexcept -> dll_iterator; constexpr auto end() noexcept -> dll_iterator; // using coro_t = boost::coroutines2::coroutine; // using pull_t = typename coro_t::pull_type; // /** // * @brief item generator // * // * @return pull_t // */ // auto items() noexcept -> pull_t // { // auto func = [&](typename coro_t::push_type& yield) { // auto cur = this->next; // while (cur != this) // { // yield(*cur); // cur = cur->next; // } // }; // return pull_t(func); // } }; #pragma pack(pop) template class dll_iterator { private: dllink* cur; public: constexpr explicit dll_iterator(dllink* cur) noexcept : cur {cur} { } constexpr auto operator++() noexcept -> dll_iterator& { this->cur = this->cur->next; return *this; } constexpr auto operator*() noexcept -> dllink& { return *this->cur; } friend auto operator==( const dll_iterator& lhs, const dll_iterator& rhs) noexcept -> bool { return lhs.cur == rhs.cur; } friend auto operator!=( const dll_iterator& lhs, const dll_iterator& rhs) noexcept -> bool { return !(lhs == rhs); } }; template inline constexpr auto dllink::begin() noexcept -> dll_iterator { return dll_iterator {this->next}; } template inline constexpr auto dllink::end() noexcept -> dll_iterator { return dll_iterator {this}; }