tl::list enhancement

This commit is contained in:
Matthias Koefferlein 2024-09-14 13:52:25 +02:00
parent 9e55a664fb
commit 79dd2084ce
3 changed files with 287 additions and 92 deletions

View File

@ -109,16 +109,130 @@ private:
bool m_owned;
};
/**
* @brief An iterator for the linked list
*/
template <class C>
class list_iterator
{
public:
typedef std::bidirectional_iterator_tag category;
typedef C value_type;
typedef C &reference;
typedef C *pointer;
list_iterator (C *p = 0) : mp_p (p) { }
list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
list_iterator operator++ (int)
{
list_iterator r = *this;
++*this;
return r;
}
list_iterator operator-- (int)
{
list_iterator r = *this;
--*this;
return r;
}
C *operator-> () const
{
return mp_p;
}
C &operator* () const
{
return *mp_p;
}
bool operator== (list_iterator other) const { return mp_p == other.mp_p; }
bool operator!= (list_iterator other) const { return mp_p != other.mp_p; }
private:
C *mp_p;
};
/**
* @brief A reverse iterator for the linked list
*/
template <class C>
class reverse_list_iterator
{
public:
typedef std::bidirectional_iterator_tag category;
typedef C value_type;
typedef C &reference;
typedef C *pointer;
reverse_list_iterator (C *p = 0) : mp_p (p) { }
reverse_list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
reverse_list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
reverse_list_iterator operator++ (int)
{
reverse_list_iterator r = *this;
++*this;
return r;
}
reverse_list_iterator operator-- (int)
{
reverse_list_iterator r = *this;
--*this;
return r;
}
C *operator-> () const
{
return mp_p;
}
C &operator* () const
{
return *mp_p;
}
bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; }
bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; }
private:
C *mp_p;
};
template <class C>
class list_impl<C, false>
{
public:
typedef list_iterator<C> iterator;
typedef list_iterator<const C> const_iterator;
typedef reverse_list_iterator<C> reverse_iterator;
typedef reverse_list_iterator<const C> const_reverse_iterator;
typedef C value_type;
list_impl () : m_head (), m_back ()
{
m_head.mp_next = &m_back;
m_back.mp_prev = &m_head;
}
list_impl (const list_impl &&other)
{
swap (other);
}
list_impl &operator= (const list_impl &&other)
{
if (&other != this) {
swap (other);
}
return *this;
}
list_impl (const list_impl &) { tl_assert (false); }
list_impl &operator= (const list_impl &) { tl_assert (false); return *this; }
@ -143,6 +257,18 @@ public:
}
}
void erase (iterator i)
{
erase (i.operator-> ());
}
void erase (iterator from, iterator to)
{
while (from != to) {
erase (from++);
}
}
void swap (list_impl<C, false> &other)
{
std::swap (m_head.mp_next, other.m_head.mp_next);
@ -196,14 +322,24 @@ public:
delete first ();
}
void insert (C *after, C *new_obj)
C *insert (C *after, C *new_obj)
{
insert_impl (after, new_obj, true);
return insert_impl (after, new_obj, true);
}
void insert_before (C *before, C *new_obj)
iterator insert (iterator after, C *new_obj)
{
insert_before_impl (before, new_obj, true);
return iterator (insert (after.operator-> (), new_obj));
}
C *insert_before (C *before, C *new_obj)
{
return insert_before_impl (before, new_obj, true);
}
iterator insert_before (iterator before, C *new_obj)
{
return iterator (insert_before_impl (before.operator-> (), new_obj, true));
}
void push_back (C *new_obj)
@ -216,14 +352,24 @@ public:
push_front_impl (new_obj, true);
}
void insert (C *after, C &new_obj)
C *insert (C *after, C &new_obj)
{
insert_impl (after, &new_obj, false);
return insert_impl (after, &new_obj, false);
}
void insert_before (C *before, C &new_obj)
iterator insert (iterator after, C &new_obj)
{
insert_before_impl (before, &new_obj, false);
return iterator (insert_impl (after.operator-> (), &new_obj, false));
}
C *insert_before (C *before, C &new_obj)
{
return insert_before_impl (before, &new_obj, false);
}
iterator insert_before (iterator before, C &new_obj)
{
return iterator (insert_before_impl (before.operator-> (), &new_obj, false));
}
void push_back (C &new_obj)
@ -269,7 +415,7 @@ protected:
private:
list_node<C> m_head, m_back;
void insert_impl (C *after, C *new_obj, bool owned)
C *insert_impl (C *after, C *new_obj, bool owned)
{
list_node<C> *after_node = after;
if (! after) {
@ -281,9 +427,11 @@ private:
after_node->mp_next = new_obj;
new_obj->mp_prev = after_node;
new_obj->mp_next->mp_prev = new_obj;
return new_obj;
}
void insert_before_impl (C *before, C *new_obj, bool owned)
C *insert_before_impl (C *before, C *new_obj, bool owned)
{
list_node<C> *before_node = before;
if (! before) {
@ -295,6 +443,8 @@ private:
before_node->mp_prev = new_obj;
new_obj->mp_next = before_node;
new_obj->mp_prev->mp_next = new_obj;
return new_obj;
}
void push_back_impl (C *new_obj, bool owned)
@ -313,6 +463,11 @@ class list_impl<C, true>
: public list_impl<C, false>
{
public:
typedef typename list_impl<C, false>::iterator iterator;
typedef typename list_impl<C, false>::const_iterator const_iterator;
typedef typename list_impl<C, false>::reverse_iterator reverse_iterator;
typedef typename list_impl<C, false>::const_reverse_iterator const_reverse_iterator;
using list_impl<C, false>::insert;
using list_impl<C, false>::push_back;
using list_impl<C, false>::pop_back;
@ -339,14 +494,52 @@ public:
return *this;
}
void insert (C *after, const C &obj)
C *insert (C *after, const C &obj)
{
insert (after, new C (obj));
return insert (after, new C (obj));
}
void insert_before (C *before, const C &obj)
iterator insert (iterator after, const C &obj)
{
insert_before (before, new C (obj));
return insert (after, new C (obj));
}
template <class Iter>
iterator insert (iterator after, Iter from, Iter to)
{
if (from == to) {
return after;
} else {
iterator first = this->insert (after, *from++);
for (iterator next = first; from != to; ++from) {
next = this->insert (next, *from);
}
return first;
}
}
C *insert_before (C *before, const C &obj)
{
return insert_before (before, new C (obj));
}
iterator insert_before (iterator before, const C &obj)
{
return insert_before (before, new C (obj));
}
template <class Iter>
iterator insert_before (iterator before, Iter from, Iter to)
{
if (from == to) {
return before;
} else {
iterator first = this->insert_before (before, *from++);
for (iterator next = first; from != to; ++from) {
next = this->insert (next, *from);
}
return first;
}
}
void push_back (const C &obj)
@ -360,72 +553,6 @@ public:
}
};
/**
* @brief An iterator for the linked list
*/
template <class C>
class list_iterator
{
public:
typedef std::bidirectional_iterator_tag category;
typedef C value_type;
typedef C &reference;
typedef C *pointer;
list_iterator (C *p = 0) : mp_p (p) { }
list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
C *operator-> () const
{
return mp_p;
}
C &operator* () const
{
return *mp_p;
}
bool operator== (list_iterator other) const { return mp_p == other.mp_p; }
bool operator!= (list_iterator other) const { return mp_p != other.mp_p; }
private:
C *mp_p;
};
/**
* @brief A reverse iterator for the linked list
*/
template <class C>
class reverse_list_iterator
{
public:
typedef std::bidirectional_iterator_tag category;
typedef C value_type;
typedef C &reference;
typedef C *pointer;
reverse_list_iterator (C *p = 0) : mp_p (p) { }
reverse_list_iterator operator++ () { mp_p = static_cast<C *> (mp_p->mp_prev); return *this; }
reverse_list_iterator operator-- () { mp_p = static_cast<C *> (mp_p->mp_next); return *this; }
C *operator-> () const
{
return mp_p;
}
C &operator* () const
{
return *mp_p;
}
bool operator== (reverse_list_iterator other) const { return mp_p == other.mp_p; }
bool operator!= (reverse_list_iterator other) const { return mp_p != other.mp_p; }
private:
C *mp_p;
};
/**
* @brief A linked list
*
@ -448,12 +575,10 @@ class list
: public list_impl<C, CanCopy>
{
public:
typedef list_iterator<C> iterator;
typedef list_iterator<const C> const_iterator;
typedef reverse_list_iterator<C> reverse_iterator;
typedef reverse_list_iterator<const C> const_reverse_iterator;
typedef C value_type;
typedef typename list_impl<C, CanCopy>::iterator iterator;
typedef typename list_impl<C, CanCopy>::const_iterator const_iterator;
typedef typename list_impl<C, CanCopy>::reverse_iterator reverse_iterator;
typedef typename list_impl<C, CanCopy>::const_reverse_iterator const_reverse_iterator;
using list_impl<C, CanCopy>::first;
using list_impl<C, CanCopy>::last;

View File

@ -98,14 +98,17 @@ static int64_t ns_time ()
#elif defined(_MSC_VER)
FILETIME ft;
GetSystemTimeAsFileTime (&ft);
static LARGE_INTEGER freq = { 0 };
uint64_t t = (uint64_t (ft.dwHighDateTime) << (sizeof (ft.dwHighDateTime) * 8)) | uint64_t (ft.dwLowDateTime);
t -= ft_to_epoch_offset;
if (freq.QuadPart == 0) {
QueryPerformanceFrequency (&freq);
tl_assert (freq.QuadPart > 0);
}
// FILETIME uses 100ns resolution, hence multiply with 100 to get ns:
return int64_t (t) * 100;
LARGE_INTEGER qpc;
QueryPerformanceCounter (&qpc);
return int64_t (double (qpc.QuadPart) / double (freq.QuadPart) * 1e9 + 0.5);
#else

View File

@ -403,3 +403,70 @@ TEST(2_BasicNoCopy)
EXPECT_EQ (obj_count, size_t (0)); // mc2 gone as well
}
TEST(3_Insert)
{
obj_count = 0;
tl::list<MyClass1> l1;
tl::list<MyClass1>::iterator i1;
EXPECT_EQ (l1.empty (), true);
EXPECT_EQ (l1.size (), size_t (0));
EXPECT_EQ (l2s (l1), "");
l1.push_back (MyClass1 (42));
EXPECT_EQ (l2s (l1), "42");
EXPECT_EQ (l1.size (), size_t (1));
i1 = l1.insert_before (l1.end (), MyClass1 (17));
EXPECT_EQ (l2s (l1), "42,17");
EXPECT_EQ (i1->n, 17);
EXPECT_EQ (l1.size (), size_t (2));
i1 = l1.insert_before (i1, MyClass1 (11));
EXPECT_EQ (l2s (l1), "42,11,17");
EXPECT_EQ (i1->n, 11);
EXPECT_EQ (l1.size (), size_t (3));
i1 = l1.insert (i1, MyClass1 (12));
EXPECT_EQ (l2s (l1), "42,11,12,17");
EXPECT_EQ (i1->n, 12);
EXPECT_EQ (l1.size (), size_t (4));
MyClass1 arr[3] = { MyClass1 (1), MyClass1 (2), MyClass1 (3) };
i1 = l1.insert (i1, arr + 0, arr + 0);
EXPECT_EQ (l2s (l1), "42,11,12,17");
EXPECT_EQ (i1->n, 12);
EXPECT_EQ (l1.size (), size_t (4));
i1 = l1.insert (i1, arr + 0, arr + 3);
EXPECT_EQ (l2s (l1), "42,11,12,1,2,3,17");
EXPECT_EQ (i1->n, 1);
EXPECT_EQ (l1.size (), size_t (7));
l1.clear ();
l1.push_back (MyClass1 (42));
i1 = l1.insert_before (l1.end (), MyClass1 (17));
EXPECT_EQ (l2s (l1), "42,17");
EXPECT_EQ (i1->n, 17);
EXPECT_EQ (l1.size (), size_t (2));
i1 = l1.insert_before (i1, arr + 0, arr + 0);
EXPECT_EQ (l2s (l1), "42,17");
EXPECT_EQ (i1->n, 17);
EXPECT_EQ (l1.size (), size_t (2));
i1 = l1.insert_before (i1, arr + 0, arr + 3);
EXPECT_EQ (l2s (l1), "42,1,2,3,17");
EXPECT_EQ (i1->n, 1);
EXPECT_EQ (l1.size (), size_t (5));
// test erase range
l1.erase (i1, l1.end ());
EXPECT_EQ (l2s (l1), "42");
EXPECT_EQ (l1.size (), size_t (1));
}