std::forward_list::unique(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME πŸ’…

std::forward_list::unique β€” okay so this page is literally all about std::forward_list::unique, bestie. It lives in the <purple>C++ Standard Libary</purple> manual (spelling is hers, not mine πŸ’€). She removes consecutive duplicate elements from a forward_list, and she has opinions about which one gets to stay.


🌸 Synopsis 🌸

okay so here's the signature situation, copied exactly so nobody comes for me:

void unique();                                 (since C++11)
                                               (until C++20)
size_type unique();                            (since C++20)
template< class BinaryPredicate >      (1)                   (since C++11)
void unique( BinaryPredicate p );          (2)               (until C++20)
template< class BinaryPredicate >                            (since C++20)
size_type unique( BinaryPredicate p );

The vibe: she removes all consecutive duplicate elements from the container. Only the first element in each group of equal elements is left. And she invalidates only the iterators and references to the removed elements β€” so specific, honestly iconic ✨

  1. Uses operator== to compare the elements.
  2. Uses p to compare the elements.
⚠️ The behavior is undefined if the corresponding comparator does not establish an equivalence relation. Like, actually undefined, bestie β€” do not play with that πŸ™ˆ

πŸŽ€ Parameters πŸŽ€

  • p β€” a binary predicate which returns true if the elements should be treated as equal.

The signature of the predicate function should be equivalent to the following:

bool pred(const Type1 &a, const Type2 &b);

While the signature does not need to have const &, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category (thus, Type1 & is not allowed, nor is Type1 unless for Type1 a move is equivalent to a copy (since C++11)).

The types Type1 and Type2 must be such that an object of type forward_list<T,Allocator>::const_iterator can be dereferenced and then implicitly converted to both of them.


πŸ¦‹ Type requirements πŸ¦‹

  • BinaryPredicate must meet the requirements of BinaryPredicate β€” yes, she said what she said πŸ’…

πŸ’– Return value πŸ’–

  • (none) β€” until C++20.
  • The number of elements removed β€” since C++20.

✨ Complexity ✨

If empty() is true, no comparison is performed.

Otherwise, given N as std::distance(begin(), end()):

  1. Exactly N-1 comparisons using operator==.
  2. Exactly N-1 applications of the predicate p.

🌈 Notes 🌈

  • Feature-test macro: __cpp_lib_list_remove_return_type β€” value 201806L, std (C++20), feature: change the return type.

πŸ“ Example πŸ“

// Run this code

#include <iostream>
#include <forward_list>

std::ostream& operator<< (std::ostream& os, std::forward_list<int> const& container)
{
    for (int val : container)
        os << val << ' ';
    return os << '\n';
}

int main()
{
    std::forward_list<int> c{1, 2, 2, 3, 3, 2, 1, 1, 2};
    std::cout << "Before unique(): " << c;
    const auto count1 = c.unique();
    std::cout << "After unique():  " << c
              << count1 << " elements were removed\n";

    c = {1, 2, 12, 23, 3, 2, 51, 1, 2, 2};
    std::cout << "\nBefore unique(pred): " << c;

    const auto count2 = c.unique([mod = 10](int x, int y)
    {
        return (x % mod) == (y % mod);
    });

    std::cout << "After unique(pred):  " << c
              << count2 << " elements were removed\n";
}

Output:

Before unique(): 1 2 2 3 3 2 1 1 2
After unique():  1 2 3 2 1 2
3 elements were removed

Before unique(pred): 1 2 12 23 3 2 51 1 2 2
After unique(pred):  1 2 23 2 51 2
4 elements were removed

πŸ‘‘ See also πŸ‘‘

  • unique β€” removes consecutive duplicate elements in a range (function template).

xoxo, your Unix-fluent bestie πŸ’– β€” source/version: http://cppreference.com, date: 2024.06.10.

πŸ“¦ where this page comes from