Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Suggestions for chapters 8 and 9 #39

Closed
@aharrison24

Description

Chapters 8 and 9 introduce list_pool and list_pool_iterator. A few things confused me while I read those chapters. I've listed them here in case they are useful:

Examples of using the list_pool class

list_pool has an unusual API compared to what we're used to from the STL. It was not immediately obvious to me how I was supposed to use it. I eventually discovered test_merge_sort.cpp which generates a list via the push methods on the iterator. But there are no examples of how to use the most important member functions of list_pool. And I wasn't expecting to need to read test_merge_sort.cpp when I was only on Chapter 8.

Perhaps it would help to give some brief examples in the chapters themselves? It's difficult to come up with concise examples, as the API seems to be designed to be used mostly via algorithms like generate_list. Here's my best stab at code using the list_pool API directly.

Chapter 8

This uses the queue operations. Without them I guess you have to keep calling allocate, which is probably a bit too low level.

list_pool<char> pool;
list_pool<char>::pair_type q = pool.empty_queue();
// push_xxx does mutate the pool, but not the queue. So you must
// remember to update the queue object yourself.
q = pool.push_back(q, 'c');
q = pool.push_back(q, 'd');
q = pool.push_back(q, 'e');
q = pool.push_front(q, 'b');
q = pool.push_front(q, 'a');
q = pool.push_back(q, 'f');
// If you want to print the list without using the list_iterator then I think this is
// the only way? But at least it demonstrates how to use `value` and `next`.
list_pool<char>::list_type node = q.first;
while (node != pool.end()) {
 std::cout << pool.value(node) << " ";
 node = pool.next(node);
}
free_list(pool, q.first);

Chapter 9

Using iterators to populate and print a list. Using push_back is more challenging, as you need to increment the insertion point each time, which gets messy. It's much neater to use something like the generate_list function from list_algorithm.h.

 list_pool<char> pool;
 list_pool<char>::iterator nil = list_pool<char>::iterator(pool);
 list_pool<char>::iterator list = nil;
 push_front(list, 'd');
 push_front(list, 'c');
 push_front(list, 'b');
 push_front(list, 'a');
 std::copy(list, nil, std::ostream_iterator<char>(std::cout, " "));

Why there is no pop_back

The list_pool API contains push_front and push_back, but only pop_front and not pop_back. That lack of symmetry seemed odd until I realised that you can't implement pop_back efficiently for a singly-linked list. A note to that effect might be worthwhile somewhere in Chapter 8?

pop_front does not free the removed elements

I'm still not sure whether that's a bug or whether it is by design. I suppose it means you end up with two lists sharing a common tail sequence, assuming you kept hold of your original head node. This isn't really something actionable in the write-up, but it is a thing that still bothers me.

Singly Linked List Iterator concept

I find this concept unsettling. I've not come across iterators that mutate the structure of the underlying data structure before (have I?). These iterators do a lot more than act as 'coordinates'!

The fact that the push_front and push_back friend functions inside list_pool_iterator.h return void even though they allocate new nodes is also odd. As it stands, push_front mutates the iterator, but push_back does not. I'd think it would be more useful for both of them to return an iterator to the newly created node or something. That would make them a little easier to hold correctly, and make the generate_list function easier to write.

But who am I to doubt Alex Stepanov? Would be interested to hear your thoughts on why it's designed this way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /