2012-04-29 19:04:18 +02:00
|
|
|
/*
|
|
|
|
|
LINKED-ELEMENTS.hpp - configurable intrusive single linked list template
|
|
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2012, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @file linked-elements.hpp
|
|
|
|
|
** Intrusive single linked list with optional ownership.
|
|
|
|
|
** This helper template allows to attach a number of tightly integrated
|
|
|
|
|
** elements with low overhead. Typically, these elements are to be attached
|
2023-04-20 18:53:17 +02:00
|
|
|
** once and never changed. Optionally, elements can be created using a
|
2012-04-30 04:28:16 +02:00
|
|
|
** custom allocation scheme; the holder might also take ownership. These
|
2012-04-29 19:04:18 +02:00
|
|
|
** variations in functionality are controlled by policy templates.
|
|
|
|
|
**
|
|
|
|
|
** The rationale for using this approach is
|
|
|
|
|
** - variable number of elements
|
|
|
|
|
** - explicit support for polymorphism
|
|
|
|
|
** - no need to template the holder on the number of elements
|
|
|
|
|
** - no heap allocations (contrast this to using std::vector)
|
|
|
|
|
** - clear and expressive notation at the usage site
|
2012-04-30 04:28:16 +02:00
|
|
|
** - convenient access through Lumiera Forward Iterators
|
2012-04-29 19:04:18 +02:00
|
|
|
** - the need to integrate tightly with a custom allocator
|
|
|
|
|
**
|
2023-04-20 18:53:17 +02:00
|
|
|
** @note this linked list container is _intrusive_ and thus needs the help
|
|
|
|
|
** of the element type, which must *provide a pointer member* `next`.
|
2012-04-30 04:28:16 +02:00
|
|
|
** Consequently, each such node element can't be member in
|
|
|
|
|
** multiple collections at the same time
|
|
|
|
|
** @note as usual, any iterator relies on the continued existence and
|
|
|
|
|
** unaltered state of the container. There is no sanity check.
|
|
|
|
|
** @warning this container is deliberately not threadsafe
|
|
|
|
|
** @warning be sure to understand the implications of taking ownership:
|
|
|
|
|
** When adding an existing node element (by pointer) to a LinkedElements
|
|
|
|
|
** list which takes ownership, the list will attempt to destroy or de-allocate
|
|
|
|
|
** this node element when going out of scope.
|
2012-04-29 19:04:18 +02:00
|
|
|
**
|
|
|
|
|
** @see LinkedElements_test
|
|
|
|
|
** @see llist.h
|
|
|
|
|
** @see ScopedCollection
|
|
|
|
|
** @see itertools.hpp
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef LIB_LINKED_ELEMENTS_H
|
|
|
|
|
#define LIB_LINKED_ELEMENTS_H
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/error.hpp"
|
2018-03-24 05:35:13 +01:00
|
|
|
#include "lib/nocopy.hpp"
|
2012-04-29 19:04:18 +02:00
|
|
|
#include "lib/iter-adapter.hpp"
|
2012-09-03 01:49:14 +02:00
|
|
|
#include "lib/util.hpp"
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
#include <utility>
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
|
|
|
|
|
|
|
|
|
namespace error = lumiera::error;
|
2018-04-02 01:48:51 +02:00
|
|
|
using error::LERR_(INDEX_BOUNDS);
|
2012-09-03 01:49:14 +02:00
|
|
|
using util::unConst;
|
2012-04-30 04:28:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace linked_elements { ///< allocation policies for the LinkedElements list container
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Policy for LinkedElements: taking ownership
|
|
|
|
|
* and possibly creating heap allocated Nodes
|
2023-04-20 18:53:17 +02:00
|
|
|
* @note is util::MoveOnly to enforce ownership
|
|
|
|
|
* on behalf of LinkedElements
|
2012-04-30 04:28:16 +02:00
|
|
|
*/
|
|
|
|
|
struct OwningHeapAllocated
|
2023-04-20 18:53:17 +02:00
|
|
|
: util::MoveOnly
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
|
|
|
|
typedef void* CustomAllocator;
|
|
|
|
|
|
|
|
|
|
/** this policy discards elements
|
|
|
|
|
* by deallocating them from heap
|
|
|
|
|
*/
|
|
|
|
|
template<class X>
|
|
|
|
|
void
|
|
|
|
|
destroy (X* elm)
|
|
|
|
|
{
|
|
|
|
|
delete elm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** this policy creates new elements
|
|
|
|
|
* simply by heap allocation */
|
2023-04-20 18:53:17 +02:00
|
|
|
template<class TY, typename...ARGS>
|
2012-04-30 04:28:16 +02:00
|
|
|
TY&
|
2023-04-20 18:53:17 +02:00
|
|
|
create (ARGS&& ...args)
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
2023-04-20 18:53:17 +02:00
|
|
|
return *new TY (std::forward<ARGS> (args)...);
|
2012-04-30 04:28:16 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Policy for LinkedElements: never create or destroy
|
|
|
|
|
* any elements, only allow to add already existing nodes.
|
|
|
|
|
* @note any added node needs to provide a \c next pointer
|
|
|
|
|
* field, which is used ("intrusively") for managing
|
|
|
|
|
* the list datastructure. But besides that, the
|
|
|
|
|
* node element won't be altered or discarded
|
|
|
|
|
* in any way.
|
|
|
|
|
*/
|
|
|
|
|
struct NoOwnership
|
|
|
|
|
{
|
|
|
|
|
typedef void* CustomAllocator;
|
|
|
|
|
|
|
|
|
|
/** this policy doesn't take ownership
|
|
|
|
|
* and thus never discards anything
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
destroy (void*)
|
|
|
|
|
{
|
|
|
|
|
/* does nothing */
|
|
|
|
|
}
|
2023-04-20 18:53:17 +02:00
|
|
|
|
|
|
|
|
template<class TY, typename...ARGS>
|
|
|
|
|
TY&
|
|
|
|
|
create (ARGS&&...)
|
|
|
|
|
{
|
|
|
|
|
static_assert ("NoOwnership allocation strategy can not allocate elements");
|
|
|
|
|
} // ... you'll have to do that yourself (that's the whole point of using this strategy)
|
2012-04-30 04:28:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LIB_ALLOCATION_CLUSTER_H
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Policy for LinkedElements: especially using a
|
|
|
|
|
* lib::AllocationCluster instance for creating
|
|
|
|
|
* new node elements. It is mandatory to pass
|
|
|
|
|
* this cluster instance to the ctor of any
|
|
|
|
|
* LinkedElements list using this policy
|
|
|
|
|
* @note AllocationCluster always de-allocates
|
|
|
|
|
* any created elements in one sway.
|
|
|
|
|
*/
|
|
|
|
|
struct UseAllocationCluster
|
|
|
|
|
{
|
|
|
|
|
typedef AllocationCluster& CustomAllocator;
|
|
|
|
|
|
|
|
|
|
CustomAllocator cluster_;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
explicit
|
|
|
|
|
UseAllocationCluster (CustomAllocator clu)
|
|
|
|
|
: cluster_(clu)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** while this policy indeed implies creating and owing
|
|
|
|
|
* new objects, the AllocationCluster doesn't support
|
|
|
|
|
* discarding individual instances. All created objects
|
|
|
|
|
* within the cluster will be bulk de-allocated
|
|
|
|
|
* when the cluster as such goes out of scope.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
destroy (void*)
|
|
|
|
|
{
|
|
|
|
|
/* does nothing */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
template<class TY, typename...ARGS>
|
|
|
|
|
TY&
|
|
|
|
|
create (ARGS&& ...args)
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
2023-04-20 18:53:17 +02:00
|
|
|
return cluster_.create<TY> (std::forward<ARGS> (args)...);
|
2012-04-30 04:28:16 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif //(End)if lib/allocation-cluster.hpp was included
|
|
|
|
|
|
|
|
|
|
}//(END)namespace linked_elements
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2012-04-30 04:28:16 +02:00
|
|
|
* Intrusive single linked list, possibly taking ownership of node elements.
|
|
|
|
|
* Additional elements can be pushed (prepended) to the list; element access
|
|
|
|
|
* is per index number (slow) or through an Lumiera Forward Iterator traversing
|
|
|
|
|
* the linked list. There is no support for changing the list contents aside
|
|
|
|
|
* of discarding any element in the list.
|
|
|
|
|
*
|
|
|
|
|
* The allocation and ownership related behaviour is controlled by a policy class
|
|
|
|
|
* provided as template parameter. When this policy supports creation of new
|
|
|
|
|
* elements, these might be created and prepended in one step.
|
2012-04-29 19:04:18 +02:00
|
|
|
*/
|
|
|
|
|
template
|
2012-04-30 04:28:16 +02:00
|
|
|
< class N ///< node class or Base/Interface class for nodes
|
|
|
|
|
, class ALO = linked_elements::OwningHeapAllocated
|
2012-04-29 19:04:18 +02:00
|
|
|
>
|
|
|
|
|
class LinkedElements
|
2023-04-20 18:53:17 +02:00
|
|
|
: ALO
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
2012-04-30 04:28:16 +02:00
|
|
|
N* head_;
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
public:
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2023-04-18 20:02:36 +02:00
|
|
|
~LinkedElements()
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
|
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-18 20:02:36 +02:00
|
|
|
LinkedElements()
|
|
|
|
|
: head_{nullptr}
|
2012-04-29 19:04:18 +02:00
|
|
|
{ }
|
|
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
LinkedElements (LinkedElements const&) = default;
|
|
|
|
|
LinkedElements (LinkedElements&& rr)
|
|
|
|
|
: head_{rr.head_}
|
|
|
|
|
{ // possibly transfer ownership
|
|
|
|
|
rr.head_ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** @param allo custom allocator or memory manager
|
|
|
|
|
* to be used by the policy for creating and
|
|
|
|
|
* discarding of node elements
|
2012-04-29 19:04:18 +02:00
|
|
|
*/
|
2012-04-30 04:28:16 +02:00
|
|
|
explicit
|
|
|
|
|
LinkedElements (typename ALO::CustomAllocator allo)
|
2023-04-18 20:02:36 +02:00
|
|
|
: ALO{allo}
|
|
|
|
|
, head_{nullptr}
|
2012-04-30 04:28:16 +02:00
|
|
|
{ }
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** creating a LinkedElements list in RAII-style:
|
|
|
|
|
* @param elements iterator to provide all the elements
|
|
|
|
|
* to be pushed into this newly created collection
|
|
|
|
|
* @note any exception while populating the container
|
|
|
|
|
* causes already created elements to be destroyed
|
2012-04-29 19:04:18 +02:00
|
|
|
*/
|
2012-04-30 04:28:16 +02:00
|
|
|
template<class IT>
|
2023-04-20 18:53:17 +02:00
|
|
|
LinkedElements (IT&& elements)
|
2023-04-18 20:02:36 +02:00
|
|
|
: head_{nullptr}
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
2012-04-30 04:28:16 +02:00
|
|
|
try {
|
2023-04-20 18:53:17 +02:00
|
|
|
pushAll (std::forward<IT> (elements));
|
2012-04-30 04:28:16 +02:00
|
|
|
}
|
|
|
|
|
catch(...)
|
|
|
|
|
{
|
|
|
|
|
WARN (progress, "Failure while populating LinkedElements list. "
|
|
|
|
|
"All elements will be discarded");
|
|
|
|
|
clear();
|
|
|
|
|
throw;
|
|
|
|
|
} }
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** @note EX_FREE */
|
2012-04-29 19:04:18 +02:00
|
|
|
void
|
|
|
|
|
clear()
|
|
|
|
|
{
|
2012-04-30 04:28:16 +02:00
|
|
|
while (head_)
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
2012-04-30 04:28:16 +02:00
|
|
|
N* elm = head_;
|
|
|
|
|
head_ = head_->next;
|
2012-04-29 19:04:18 +02:00
|
|
|
try {
|
2012-04-30 04:28:16 +02:00
|
|
|
ALO::destroy(elm);
|
2012-04-29 19:04:18 +02:00
|
|
|
}
|
2012-04-30 04:28:16 +02:00
|
|
|
ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in LinkedElements list")
|
2012-04-29 19:04:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** convenience shortcut to add all the elements
|
|
|
|
|
* yielded by the given Lumiera Forward Iterator
|
|
|
|
|
* @note EX_SANE
|
2012-04-29 19:04:18 +02:00
|
|
|
*/
|
2012-04-30 04:28:16 +02:00
|
|
|
template<class IT>
|
2012-04-29 19:04:18 +02:00
|
|
|
void
|
2012-04-30 04:28:16 +02:00
|
|
|
pushAll (IT elements)
|
|
|
|
|
{
|
|
|
|
|
for ( ; elements; ++elements )
|
|
|
|
|
push (*elements);
|
|
|
|
|
}
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** accept the given element and prepend it to the list of elements;
|
|
|
|
|
* depending on the allocation policy, this might imply taking ownership
|
|
|
|
|
* @note EX_STRONG
|
|
|
|
|
*/
|
|
|
|
|
template<typename TY>
|
|
|
|
|
TY&
|
|
|
|
|
push (TY& elm)
|
|
|
|
|
{
|
|
|
|
|
elm.next = head_;
|
|
|
|
|
head_ = &elm;
|
|
|
|
|
return elm;
|
|
|
|
|
}
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
// template< class TY =N>
|
|
|
|
|
// TY& //_________________________________________
|
|
|
|
|
// emplace () ///< add object of type TY, using 0-arg ctor
|
|
|
|
|
// {
|
|
|
|
|
// return push (ALO::template create<TY>());
|
|
|
|
|
// }
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
/** prepend object of type TY, forwarding ctor args */
|
|
|
|
|
template<class TY =N, typename...ARGS>
|
|
|
|
|
TY&
|
|
|
|
|
emplace (ARGS&& ...args)
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
2023-04-20 18:53:17 +02:00
|
|
|
return push (ALO::template create<TY> (std::forward<ARGS> (args)...));
|
2012-04-29 19:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
/**
|
|
|
|
|
* Mutate the complete list to change the order of elements.
|
|
|
|
|
* @remark since pushing prepends, elements are initially in reverse order
|
|
|
|
|
* @warning this operation invalidates iterators and has O(n) cost;
|
|
|
|
|
* ownership and elements themselves are not affected.
|
|
|
|
|
*/
|
|
|
|
|
LinkedElements&
|
|
|
|
|
reverse()
|
2012-04-29 19:04:18 +02:00
|
|
|
{
|
2023-04-20 18:53:17 +02:00
|
|
|
if (not empty())
|
|
|
|
|
{
|
|
|
|
|
N* p = head_->next;
|
|
|
|
|
head_->next = nullptr;
|
|
|
|
|
while (p)
|
|
|
|
|
{
|
|
|
|
|
N& n = *p;
|
|
|
|
|
p = p->next;
|
|
|
|
|
push (n);
|
|
|
|
|
} }
|
|
|
|
|
return *this;
|
2012-04-29 19:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
|
2012-04-29 19:04:18 +02:00
|
|
|
/* === Element access and iteration === */
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
N&
|
2012-04-29 19:04:18 +02:00
|
|
|
operator[] (size_t index) const
|
|
|
|
|
{
|
2012-04-30 04:28:16 +02:00
|
|
|
N* p = head_;
|
2023-04-20 18:53:17 +02:00
|
|
|
while (p and index)
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
|
|
|
|
p = p->next;
|
|
|
|
|
--index;
|
|
|
|
|
}
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
if (!p or index)
|
2012-04-30 04:28:16 +02:00
|
|
|
throw error::Logic ("Attempt to access element beyond the end of LinkedElements list"
|
2018-04-02 01:48:51 +02:00
|
|
|
, LERR_(INDEX_BOUNDS));
|
2012-04-30 04:28:16 +02:00
|
|
|
else
|
|
|
|
|
return *p;
|
2012-04-29 19:04:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
/** @warning unchecked */
|
|
|
|
|
N&
|
|
|
|
|
top() const
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (head_, "NIL");
|
|
|
|
|
return *(unConst(this)->head_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/** @warning traverses to count the elements */
|
|
|
|
|
size_t
|
2023-04-20 18:53:17 +02:00
|
|
|
size() const
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
|
|
|
|
uint count=0;
|
|
|
|
|
N* p = head_;
|
|
|
|
|
while (p)
|
|
|
|
|
{
|
|
|
|
|
p = p->next;
|
|
|
|
|
++count;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
bool
|
2023-04-20 18:53:17 +02:00
|
|
|
empty() const
|
2012-04-30 04:28:16 +02:00
|
|
|
{
|
|
|
|
|
return !head_;
|
|
|
|
|
}
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2012-05-23 04:06:24 +02:00
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
* Iteration is just following the single linked list.
|
|
|
|
|
* We encapsulate this simple pointer into a dedicated marker type
|
|
|
|
|
* to ease the handling and mixing of iterators and const iterators.
|
|
|
|
|
* (Explanation: IterationState depends on our type parameters...)
|
|
|
|
|
*/
|
2012-05-19 02:16:07 +02:00
|
|
|
struct IterationState
|
|
|
|
|
{
|
|
|
|
|
N* node;
|
|
|
|
|
|
2023-04-18 20:02:36 +02:00
|
|
|
IterationState (N* p =nullptr)
|
|
|
|
|
: node{p}
|
2012-05-19 02:16:07 +02:00
|
|
|
{ }
|
|
|
|
|
|
2017-12-05 03:28:00 +01:00
|
|
|
/* ==== internal callback API for the iterator ==== */
|
|
|
|
|
|
|
|
|
|
/** Iteration-logic: switch to next position
|
|
|
|
|
* @warning assuming the given node pointer belongs to this collection.
|
|
|
|
|
* actually this is never checked; also the given node might
|
|
|
|
|
* have been deallocated in the meantime.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
iterNext()
|
|
|
|
|
{
|
|
|
|
|
node = node->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Iteration-logic: detect iteration end. */
|
|
|
|
|
bool
|
|
|
|
|
checkPoint() const
|
|
|
|
|
{
|
|
|
|
|
return bool(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
N&
|
|
|
|
|
yield() const
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (node);
|
|
|
|
|
return * unConst(this)->node;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-19 02:16:07 +02:00
|
|
|
friend bool
|
|
|
|
|
operator== (IterationState const& il, IterationState const& ir)
|
|
|
|
|
{
|
|
|
|
|
return il.node == ir.node;
|
|
|
|
|
}
|
|
|
|
|
};
|
2012-04-29 19:04:18 +02:00
|
|
|
|
2012-05-23 04:06:24 +02:00
|
|
|
public:
|
2023-04-18 20:02:36 +02:00
|
|
|
using iterator = IterStateWrapper< N, IterationState>;
|
|
|
|
|
using const_iterator = IterStateWrapper<const N, IterationState>;
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
|
2012-05-19 02:16:07 +02:00
|
|
|
iterator begin() { return iterator (head_); }
|
|
|
|
|
const_iterator begin() const { return const_iterator (head_); }
|
2012-04-30 04:28:16 +02:00
|
|
|
iterator end () { return iterator(); }
|
|
|
|
|
const_iterator end () const { return const_iterator(); }
|
2012-04-29 19:04:18 +02:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace lib
|
2023-04-18 20:02:36 +02:00
|
|
|
#endif /*LIB_LINKED_ELEMENTS_H*/
|