3

I would like to do the following:

  1. join two std::lists (l1 and l2)
  2. pass the combined list to a function
  3. restore the two original lists

All this should happen without allocating new memory.

First I wanted to try this with splice(), but then I read that the iterators of the moved items would be invalidated by splice(). Then, however, I read this SO answer: splice() on std::list and iterator invalidation and decided to try it anyway:

iterator temp = l2.begin();
l1.splice(l1.end(), l2);
my_function(l1);
l2.splice(l2.end(), l1, temp, l1.end());

This works in many cases, but if l2 is initially empty, it doesn't (because temp doesn't point to anything meaningful).

Of course I could check for l2.size() > 0, but all this seems a little too work-around-ish to me.

Does anyone know a better/cleaner solution to my initial problem?

Community
  • 1
  • 1
Matthias
  • 4,524
  • 2
  • 31
  • 50
  • 2
    If `my_function` is actually "your" function, you could make it take a starting and ending iterator...and then make a generalized aggregate iterator class which handled the logic of stepping across multiple collections...? – HostileFork says dont trust SE Oct 06 '11 at 23:40
  • @HostileFork: thanks for your comment, I thought about this but such a fancy iterator seemed a little too much effort for my task at hand. But the real downside would be that I always would have to use the _fancy iterator_, even if I have only one simple list. I didn't mention this, but I want to be able to use `my_function()` some times with a single list and other times with a combined list, this is _not_ a compile-time decision. – Matthias Oct 07 '11 at 10:31
  • I don't understand what you mean by "not a compile-time decision", but in any case the *fancy iterator* could reduce very simply into the normal iterator in the single list case...its begin and end methods would simply return a wrapped version of the contained list's begin and end iterators if there was only one. Pretty much no performance hit whatsoever. You can also overload `my_function` – HostileFork says dont trust SE Oct 07 '11 at 15:27
  • Sorry for the confusion. Basically I meant that `my_function` cannot be a template function. This function is called repeatedly in some worker threads and it must be the exact same function every time (no overloads). So I can have only one iterator type and this would have to be the _fancy iterator_. Anyway, I'm sure it would work but I find the list-manipulation-thingy simpler to implement and simpler to understand. – Matthias Oct 07 '11 at 17:44

1 Answers1

3

You could turn the logic around to keep a valid iterator:

auto temp = l2.begin();

l2.splice(temp, l1);  // "L2 = L1 + L2"

my_function(l2);

l1.splice(l1.end(), l2, l2.begin(), temp);  // restores both l1 and l2
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084