c++11 standard template (STL) (std::unordered_multiset) (3)

 is defined in the header file <unordered_set>
template<

class Key,
class Hash = std::hash,
class KeyEqual = std::equal_to,
class Allocator = std::allocator

> class unordered_multiset;

(1) (since C++ 11)
namespace pmr {

template class Hash = std::hash,
class Pred = std::equal_to>
using unordered_multiset = std::unordered_multiset std::pmr::polymorphic_allocator>

}

(2) (since C++ 17)

unordered_multiset is an associative container containing a collection of objects of type Key that may not be unique. Search, insertion and removal have an average constant time complexity.

Elements are not sorted in any order internally, just organized into buckets. Which bucket an element is placed in depends entirely on the hash of its value. This allows for quick access to individual elements, since once the hash is computed, it refers to the exact bucket in which the element was placed.

The iteration order of this container is not required to be stable (so e.g. std::equal cannot be used to compare two std::unordered_multiset ), except for key comparisons equivalent (with key_eq( ) for the comparator compares equal) constitutes a contiguous subrange in iteration order, which can be accessed with equal_range().

Member function

Assign to container

std::unordered_multiset<Key,Hash,KeyEqual,Allocator>::operator=

unordered_multiset & amp; operator=( const unordered_multiset & amp; other );

(1) (since C++ 11)

unordered_multiset & amp; operator=( unordered_multiset & amp; & amp; other );

(2) (since C++11)
(until C++17)

unordered_multiset & amp; operator=( unordered_multiset & amp; & amp; other ) noexcept(/* see below */);

(since C++17)

unordered_multiset & operator=( std::initializer_list ilist );

(3) (since C++ 11)

Replace container contents.

1) Copy assignment operator. Replace the content with a copy of other. If std::allocator_traits::propagate_on_container_copy_assignment::value is true , replaces the target allocator with a copy of the source allocator. If the source and target allocators do not compare equal, the memory is destroyed with the target ( *this ) allocator, then allocated with other‘s allocator before copying the element. (since C++11).,

2) Move assignment operator. Replace the content with the content of other using move semantics (i.e. move the data in other from other to this container). After other is in a legal but unspecified state. If std::allocator_traits::propagate_on_container_move_assignment::value is true , replaces the target allocator with a copy of the source allocator. If it is false and the source and target allocators do not compare equal, the target cannot take ownership of the source memory, but must move assignments element-by-element individually, allocating additional memory as needed with its own allocator. In any case, the element originally in *this is either destroyed or replaced with an element-wise move assignment.

3) Replace the contents with those identified by initializer_list ilist.

parameter

other Another container to use as a data source
ilist initializer_list used as data source

Return value

*this

Complexity

1) Linear in size of *this and other.

2) Linear in the size of *this, unless the allocator does not compare equal and does not propagate, in which case it is the same as that of *this and other The size is linear.

3) Linear in size of *this and ilist.

Exception

2) noexcept specifies: noexcept(std::allocator_traits::is_always_equal::value

& amp; & amp; std::is_nothrow_move_assignable::value

& amp; & amp; std::is_nothrow_move_assignable::value)

Note

After container move assignment (overload(2)), references, pointers, and iterators (except tail iterators) to other remain valid unless an incompatible allocator forces element-wise assignment, However the referred element is now in *this. The current standard guarantees this through blanket statements in §23.2.1[container.requirements.general]/12, while more direct guarantees are being considered under LWG 2321.

Returns the associated allocator

std::unordered_multiset<Key, Hash, KeyEqual, Allocator>::get_allocator

allocator_type get_allocator() const;

(since C++11)

Returns the allocator associated with the container.

parameter

(none)

Return value

The associated allocator.

Complexity

constant.

Call example

#include <iostream>
#include <forward_list>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <unordered_set>
#include <time.h>

using namespace std;

struct Cell
{
    int x;
    int y;

    Cell() = default;
    Cell(int a, int b): x(a), y(b) {}

    Cell & amp; operator + =(const Cell & amp; cell)
    {
        x + = cell.x;
        y + = cell.y;
        return *this;
    }

    Cell & amp; operator + (const Cell & amp; cell)
    {
        x + = cell.x;
        y + = cell.y;
        return *this;
    }

    Cell & amp; operator *(const Cell & amp; cell)
    {
        x *= cell.x;
        y *= cell.y;
        return *this;
    }

    Cell & operator + + ()
    {
        x + = 1;
        y + = 1;
        return *this;
    }


    bool operator <(const Cell & cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator >(const Cell & cell) const
    {
        if (x == cell.x)
        {
            return y > cell.y;
        }
        else
        {
            return x > cell.x;
        }
    }

    bool operator ==(const Cell & cell) const
    {
        return x == cell.x & amp; & amp; y == cell.y;
    }
};

struct myCompare
{
    bool operator()(const int & amp; a, const int & amp; b)
    {
        return a < b;
    }
};

std::ostream & amp;operator<<(std::ostream & amp;os, const Cell & amp;cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

std::ostream & amp;operator<<(std::ostream & amp;os, const std::pair<const int, Cell> & amp;pCell)
{
    os << pCell.first << "-" << pCell.second;
    return os;
}

struct CHash
{
    size_t operator()(const Cell & cell) const
    {
        size_t thash = std::hash<int>()(cell.x) | std::hash<int>()(cell.y);
// std::cout << "CHash: " <<thash << std::endl;
        return thash;
    }
};

struct CEqual
{
    bool operator()(const Cell & amp; a, const Cell & amp; b) const
    {
        return a.x == b.x & amp; & amp; a.y == b.y;
    }
};


int main()
{
    std::cout << std::boolalpha;

    std::mt19937 g{std::random_device{}()};
    srand((unsigned)time(NULL));

    auto generate = []()
    {
        int n = std::rand() % 10 + 110;
        Cell cell{n, n};
        return cell;
    };

    std::vector<Cell> vector1(6);
    std::generate(vector1. begin(), vector1. end(), generate);
    std::cout << "vector1: ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    //2) Constructs a container with content in the range [first, last).
    // Set max_load_factor() to 1.0. If more than one element in the range has a key that compares equivalent, it is unspecified which element is inserted.
    std::unordered_multiset<Cell, CHash, CEqual> unordered_multiset1(vector1.begin(), vector1.end());
    std::cout << "unordered_multiset1: ";
    std::copy(unordered_multiset1.begin(), unordered_multiset1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;


    //1) Copy assignment operator. Replace the content with a copy of other.
    std::unordered_multiset<Cell, CHash, CEqual> unordered_multiset2 = unordered_multiset1;
    std::cout << "unordered_multiset2: ";
    std::copy(unordered_multiset2.begin(), unordered_multiset2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;


    //2) Move assignment operator. Replaces the contents of other with the contents of other using move semantics (i.e. moves the data in other from other to this container).
    // After that other is in a legal but unspecified state.
    std::unordered_multiset<Cell, CHash, CEqual> unordered_multiset3 = std::move(unordered_multiset1);
    std::cout << "unordered_multiset3: ";
    std::copy(unordered_multiset3.begin(), unordered_multiset3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;


    //3) Replace the contents with those identified by the initializer_list ilist.
    std::unordered_multiset<Cell, CHash, CEqual> unordered_multiset4 =
    {generate(), generate(), generate(), generate(), generate(), generate()};
    std::cout << "unordered_multiset4: ";
    std::copy(unordered_multiset4.begin(), unordered_multiset4.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    return 0;
}

output