26 Containers library [containers]

26.3 Sequence containers [sequences]

26.3.9 Class template forward_­list [forwardlist]

26.3.9.1 Class template forward_­list overview [forwardlist.overview]

A forward_­list is a container that supports forward iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically. Fast random access to list elements is not supported. [Note: It is intended that forward_­list have zero space or time overhead relative to a hand-written C-style singly linked list. Features that would conflict with that goal have been omitted.end note]

A forward_­list satisfies all of the requirements of a container, except that the size() member function is not provided and operator== has linear complexity. A forward_­list also satisfies all of the requirements for an allocator-aware container. In addition, a forward_­list provides the assign member functions (Table 87) and several of the optional container requirements. Descriptions are provided here only for operations on forward_­list that are not described in that table or for operations where there is additional semantic information.

[Note: Modifying any list requires access to the element preceding the first element of interest, but in a forward_­list there is no constant-time way to access a preceding element. For this reason, ranges that are modified, such as those supplied to erase and splice, must be open at the beginning. end note]

namespace std {
  template <class T, class Allocator = allocator<T>>
  class forward_list {
  public:
    // types:
    using value_type      = T;
    using allocator_type  = Allocator;
    using pointer         = typename allocator_traits<Allocator>::pointer;
    using const_pointer   = typename allocator_traits<Allocator>::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;
    using size_type       = implementation-defined; // see [container.requirements]
    using difference_type = implementation-defined; // see [container.requirements]
    using iterator        = implementation-defined; // see [container.requirements]
    using const_iterator  = implementation-defined; // see [container.requirements]

    // [forwardlist.cons], construct/copy/destroy
    forward_list() : forward_list(Allocator()) { }
    explicit forward_list(const Allocator&);
    explicit forward_list(size_type n, const Allocator& = Allocator());
    forward_list(size_type n, const T& value,
                 const Allocator& = Allocator());
    template <class InputIterator>
      forward_list(InputIterator first, InputIterator last,
                   const Allocator& = Allocator());
    forward_list(const forward_list& x);
    forward_list(forward_list&& x);
    forward_list(const forward_list& x, const Allocator&);
    forward_list(forward_list&& x, const Allocator&);
    forward_list(initializer_list<T>, const Allocator& = Allocator());
    ~forward_list();
    forward_list& operator=(const forward_list& x);
    forward_list& operator=(forward_list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    forward_list& operator=(initializer_list<T>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const T& t);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // [forwardlist.iter], iterators
    iterator before_begin() noexcept;
    const_iterator before_begin() const noexcept;
    iterator begin() noexcept;
    const_iterator begin() const noexcept;
    iterator end() noexcept;
    const_iterator end() const noexcept;

    const_iterator cbegin() const noexcept;
    const_iterator cbefore_begin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type max_size() const noexcept;

    // [forwardlist.access], element access
    reference front();
    const_reference front() const;

    // [forwardlist.modifiers], modifiers
    template <class... Args> reference emplace_front(Args&&... args);
    void push_front(const T& x);
    void push_front(T&& x);
    void pop_front();

    template <class... Args> iterator emplace_after(const_iterator position, Args&&... args);
    iterator insert_after(const_iterator position, const T& x);
    iterator insert_after(const_iterator position, T&& x);

    iterator insert_after(const_iterator position, size_type n, const T& x);
    template <class InputIterator>
      iterator insert_after(const_iterator position, InputIterator first, InputIterator last);
    iterator insert_after(const_iterator position, initializer_list<T> il);

    iterator erase_after(const_iterator position);
    iterator erase_after(const_iterator position, const_iterator last);
    void swap(forward_list&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);

    void resize(size_type sz);
    void resize(size_type sz, const value_type& c);
    void clear() noexcept;

    // [forwardlist.ops], forward_­list operations
    void splice_after(const_iterator position, forward_list& x);
    void splice_after(const_iterator position, forward_list&& x);
    void splice_after(const_iterator position, forward_list& x,
                      const_iterator i);
    void splice_after(const_iterator position, forward_list&& x,
                      const_iterator i);
    void splice_after(const_iterator position, forward_list& x,
                      const_iterator first, const_iterator last);
    void splice_after(const_iterator position, forward_list&& x,
                      const_iterator first, const_iterator last);

    void remove(const T& value);
    template <class Predicate> void remove_if(Predicate pred);

    void unique();
    template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

    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);

    void sort();
    template <class Compare> void sort(Compare comp);

    void reverse() noexcept;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    forward_list(InputIterator, InputIterator, Allocator = Allocator())
      -> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>;

  template <class T, class Allocator>
    bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);

  // [forwardlist.spec], specialized algorithms
  template <class T, class Allocator>
    void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

An incomplete type T may be used when instantiating forward_­list if the allocator satisfies the allocator completeness requirements. T shall be complete before any member of the resulting specialization of forward_­list is referenced.

26.3.9.2 forward_­list constructors, copy, assignment [forwardlist.cons]

explicit forward_list(const Allocator&);

Effects: Constructs an empty forward_­list object using the specified allocator.

Complexity: Constant.

explicit forward_list(size_type n, const Allocator& = Allocator());

Effects: Constructs a forward_­list object with n default-inserted elements using the specified allocator.

Requires: T shall be DefaultInsertable into *this.

Complexity: Linear in n.

forward_list(size_type n, const T& value, const Allocator& = Allocator());

Effects: Constructs a forward_­list object with n copies of value using the specified allocator.

Requires: T shall be CopyInsertable into *this.

Complexity: Linear in n.

template <class InputIterator> forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator());

Effects: Constructs a forward_­list object equal to the range [first, last).

Complexity: Linear in distance(first, last).

26.3.9.3 forward_­list iterators [forwardlist.iter]

iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept;

Returns: A non-dereferenceable iterator that, when incremented, is equal to the iterator returned by begin().

Effects: cbefore_­begin() is equivalent to const_­cast<forward_­list const&>(*this).before_­begin().

Remarks: before_­begin() == end() shall equal false.

26.3.9.4 forward_­list element access [forwardlist.access]

reference front(); const_reference front() const;

Returns: *begin()

26.3.9.5 forward_­list modifiers [forwardlist.modifiers]

None of the overloads of insert_­after shall affect the validity of iterators and references, and erase_­after shall invalidate only iterators and references to the erased elements. If an exception is thrown during insert_­after there shall be no effect. Inserting n elements into a forward_­list is linear in n, and the number of calls to the copy or move constructor of T is exactly equal to n. Erasing n elements from a forward_­list is linear in n and the number of calls to the destructor of type T is exactly equal to n.

template <class... Args> reference emplace_front(Args&&... args);

Effects: Inserts an object of type value_­type constructed with value_­type(std​::​forward<Args>(​args)...) at the beginning of the list.

void push_front(const T& x); void push_front(T&& x);

Effects: Inserts a copy of x at the beginning of the list.

void pop_front();

Effects: As if by erase_­after(before_­begin()).

iterator insert_after(const_iterator position, const T& x); iterator insert_after(const_iterator position, T&& x);

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()).

Effects: Inserts a copy of x after position.

Returns: An iterator pointing to the copy of x.

iterator insert_after(const_iterator position, size_type n, const T& x);

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()).

Effects: Inserts n copies of x after position.

Returns: An iterator pointing to the last inserted copy of x or position if n == 0.

template <class InputIterator> iterator insert_after(const_iterator position, InputIterator first, InputIterator last);

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()). first and last are not iterators in *this.

Effects: Inserts copies of elements in [first, last) after position.

Returns: An iterator pointing to the last inserted element or position if first == last.

iterator insert_after(const_iterator position, initializer_list<T> il);

Effects: insert_­after(p, il.begin(), il.end()).

Returns: An iterator pointing to the last inserted element or position if il is empty.

template <class... Args> iterator emplace_after(const_iterator position, Args&&... args);

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()).

Effects: Inserts an object of type value_­type constructed with value_­type(std​::​forward<Args>(​args)...) after position.

Returns: An iterator pointing to the new object.

iterator erase_after(const_iterator position);

Requires: The iterator following position is dereferenceable.

Effects: Erases the element pointed to by the iterator following position.

Returns: An iterator pointing to the element following the one that was erased, or end() if no such element exists.

Throws: Nothing.

iterator erase_after(const_iterator position, const_iterator last);

Requires: All iterators in the range (position, last) are dereferenceable.

Effects: Erases the elements in the range (position, last).

Returns: last.

Throws: Nothing.

void resize(size_type sz);

Effects: If sz < distance(begin(), end()), erases the last distance(begin(), end()) - sz elements from the list. Otherwise, inserts sz - distance(begin(), end()) default-inserted elements at the end of the list.

Requires: T shall be DefaultInsertable into *this.

void resize(size_type sz, const value_type& c);

Effects: If sz < distance(begin(), end()), erases the last distance(begin(), end()) - sz elements from the list. Otherwise, inserts sz - distance(begin(), end()) copies of c at the end of the list.

Requires: T shall be CopyInsertable into *this.

void clear() noexcept;

Effects: Erases all elements in the range [begin(), end()).

Remarks: Does not invalidate past-the-end iterators.

26.3.9.6 forward_­list operations [forwardlist.ops]

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

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()). get_­allocator() == x.get_­allocator(). &x != this.

Effects: Inserts the contents of x after position, and x becomes empty. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.

Throws: Nothing.

Complexity: O(distance(x.begin(), x.end()))

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

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()). The iterator following i is a dereferenceable iterator in x. get_­allocator() == x.get_­allocator().

Effects: Inserts the element following i into *this, following position, and removes it from x. The result is unchanged if position == i or position == ++i. Pointers and references to *++i continue to refer to the same element but as a member of *this. Iterators to *++i continue to refer to the same element, but now behave as iterators into *this, not into x.

Throws: Nothing.

Complexity: O(1)

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

Requires: position is before_­begin() or is a dereferenceable iterator in the range [begin(), end()). (first, last) is a valid range in x, and all iterators in the range (first, last) are dereferenceable. position is not an iterator in the range (first, last). get_­allocator() == x.get_­allocator().

Effects: Inserts elements in the range (first, last) after position and removes the elements from x. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.

Complexity: O(distance(first, last))

void remove(const T& value); template <class Predicate> void remove_if(Predicate pred);

Effects: Erases all the elements in the list referred by a list iterator i for which the following conditions hold: *i == value (for remove()), pred(*i) is true (for remove_­if()). Invalidates only the iterators and references to the erased elements.

Throws: Nothing unless an exception is thrown by the equality comparison or the predicate.

Remarks: Stable.

Complexity: Exactly distance(begin(), end()) applications of the corresponding predicate.

void unique(); template <class BinaryPredicate> void unique(BinaryPredicate pred);

Effects: Erases all but the first element from every consecutive group of equal elements referred to by the iterator i in the range [first + 1, last) for which *i == *(i-1) (for the version with no arguments) or pred(*i, *(i - 1)) (for the version with a predicate argument) holds. Invalidates only the iterators and references to the erased elements.

Throws: Nothing unless an exception is thrown by the equality comparison or the predicate.

Complexity: If the range [first, last) is not empty, exactly (last - first) - 1 applications of the corresponding predicate, otherwise no applications of the predicate.

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);

Requires: comp defines a strict weak ordering, and *this and x are both sorted according to this ordering. get_­allocator() == x.get_­allocator().

Effects: Merges the two sorted ranges [begin(), end()) and [x.begin(), x.end()). x is empty after the merge. If an exception is thrown other than by a comparison there are no effects. Pointers and references to the moved elements of x now refer to those same elements but as members of *this. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.

Remarks: Stable. The behavior is undefined if get_­allocator() != x.get_­allocator().

Complexity: At most distance(begin(), end()) + distance(x.begin(), x.end()) - 1 comparisons.

void sort(); template <class Compare> void sort(Compare comp);

Requires: operator< (for the version with no arguments) or comp (for the version with a comparison argument) defines a strict weak ordering.

Effects: Sorts the list according to the operator< or the comp function object. If an exception is thrown, the order of the elements in *this is unspecified. Does not affect the validity of iterators and references.

Remarks: Stable.

Complexity: Approximately NlogN comparisons, where N is distance(begin(), end()).

void reverse() noexcept;

Effects: Reverses the order of the elements in the list. Does not affect the validity of iterators and references.

Complexity: Linear time.

26.3.9.7 forward_­list specialized algorithms [forwardlist.spec]

template <class T, class Allocator> void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: As if by x.swap(y).