1310. forward_list splice_after from lvalues

Section: 23.3.7.6 [forward.list.ops] Status: C++11 Submitter: Howard Hinnant Opened: 2010-02-05 Last modified: 2023-02-07

Priority: Not Prioritized

View all other issues in [forward.list.ops].

View all issues with C++11 status.

Discussion:

We've moved 1133 to Tentatively Ready and I'm fine with that.

1133 adds lvalue-references to the splice signatures for list. So now list can splice from lvalue and rvalue lists (which was the intent of the original move papers btw). During the discussion of this issue it was mentioned that if we want to give the same treatment to forward_list, that should be a separate issue.

This is that separate issue.

Consider the following case where you want to splice elements from one place in a forward_list to another. Currently this must be coded like so:

fl.splice_after(to_here, std::move(fl), from1, from2);

This looks pretty shocking to me. I would expect to be able to code instead:

fl.splice_after(to_here, fl, from1, from2);

but we currently don't allow it.

When I say move(fl), I consider that as saying that I don't care about the value of fl any more (until I assign it a new value). But in the above example, this simply isn't true. I do care about the value of fl after the move, and I'm not assigning it a new value. I'm merely permuting its current value.

I propose adding forward_list& overloads to the 3 splice_after members. For consistency's sake (principal of least surprise) I'm also proposing to overload merge this way as well.

Proposed resolution:

Add to the synopsis of [forwardlist.overview]:

template <class T, class Allocator = allocator<T> >
class forward_list {
public:
  ...
  // [forwardlist.ops], forward_list operations:
  void splice_after(const_iterator p, forward_list& x);
  void splice_after(const_iterator p, forward_list&& x);
  void splice_after(const_iterator p, forward_list& x, const_iterator i);
  void splice_after(const_iterator p, forward_list&& x, const_iterator i);
  void splice_after(const_iterator p, forward_list& x,
                    const_iterator first, const_iterator last);
  void splice_after(const_iterator p, forward_list&& x,
                    const_iterator first, const_iterator last);
  ...
  void merge(forward_list& x);
  void merge(forward_list&& x);
  template <class Compare> void merge(forward_list& x, Compare comp);
  template <class Compare> void merge(forward_list&& x, Compare comp);
  ...
};

Add to the signatures of [forwardlist.ops]:

void splice_after(const_iterator p, forward_list& x);
void splice_after(const_iterator p, forward_list&& x);

1 ...

void splice_after(const_iterator p, forward_list& x, const_iterator i);
void splice_after(const_iterator p, forward_list&& x, const_iterator i);

4 ...

void splice_after(const_iterator p, forward_list& x,
                const_iterator first, const_iterator last);
void splice_after(const_iterator p, forward_list&& x,
                const_iterator first, const_iterator last);

7 ...

void merge(forward_list& x);
void merge(forward_list&& x);
template <class Compare> void merge(forward_list& x, Compare comp);
template <class Compare> void merge(forward_list&& x, Compare comp);

16 ...