Boost C++ 函式庫

...世界上最受推崇且設計最精良的 C++ 函式庫專案之一。 Herb SutterAndrei Alexandrescu, C++ 編碼規範

簡介

雜湊表是一種非常流行的電腦資料結構,幾乎可以在任何程式語言中以某種形式找到。其他關聯式結構,例如 rb 樹(C++ 中由 std::setstd::map 使用)在插入和查找方面具有對數時間複雜度,而雜湊表(如果配置得當)平均以常數時間執行這些操作,並且通常快得多。

C++ 在 C++11 中引入了無序關聯式容器 std::unordered_setstd::unordered_mapstd::unordered_multisetstd::unordered_multimap,但自那時以來,對雜湊表的研究並未停止:CPU 架構的進步,例如更強大的快取、SIMD 操作和日益普及的 多核心處理器,為改進的基於雜湊的資料結構和 2011 年指定的無序關聯式容器無法達到的新用例開闢了可能性。

Boost.Unordered 提供了一個雜湊容器的目錄,具有不同的標準相容性層級、效能和預期的使用場景

表 1. Boost.Unordered 容器

基於節點

平坦

封閉定址

boost::unordered_set
boost::unordered_map
boost::unordered_multiset
boost::unordered_multimap

開放定址

boost::unordered_node_set
boost::unordered_node_map

boost::unordered_flat_set
boost::unordered_flat_map

並行

boost::concurrent_node_set
boost::concurrent_node_map

boost::concurrent_flat_set
boost::concurrent_flat_map

  • 封閉定址容器 完全符合 C++ 無序關聯式容器的規範,並在所需標準介面所施加的技術限制內,具有市場上最快的實作之一。

  • 開放定址容器 依賴於快得多的資料結構和演算法(在典型情境下快 2 倍以上),同時略微偏離標準介面以適應實作。 有兩種變體:平坦式(最快)和基於節點式,後者在重新雜湊時提供指標穩定性,但代價是速度較慢。

  • 最後,並行容器 的設計和實作旨在用於高效能多執行緒情境。 其介面與一般 C++ 容器的介面截然不同。 提供平坦式和基於節點的變體。

Boost.Unordered 中的所有 set 和 map 的實例化方式分別與 std::unordered_setstd::unordered_map 類似

namespace boost {
    template <
        class Key,
        class Hash = boost::hash<Key>,
        class Pred = std::equal_to<Key>,
        class Alloc = std::allocator<Key> >
    class unordered_set;
    // same for unordered_multiset, unordered_flat_set, unordered_node_set,
    // concurrent_flat_set and concurrent_node_set

    template <
        class Key, class Mapped,
        class Hash = boost::hash<Key>,
        class Pred = std::equal_to<Key>,
        class Alloc = std::allocator<std::pair<Key const, Mapped> > >
    class unordered_map;
    // same for unordered_multimap, unordered_flat_map, unordered_node_map,
    // concurrent_flat_map and concurrent_node_map
}

將物件儲存在無序關聯式容器中需要鍵相等函數和雜湊函數。 標準容器中的預設函數物件支援一些基本類型,包括整數類型、浮點類型、指標類型和標準字串。 由於 Boost.Unordered 使用 boost::hash,它也支援一些其他類型,包括標準容器。 若要使用這些方法不支援的任何類型,您必須擴充 Boost.Hash 以支援該類型或使用您自己的自訂相等謂詞和雜湊函數。 如需詳細資訊,請參閱 相等謂詞和雜湊函數 章節。

雜湊表基礎

容器由許多桶子組成,每個桶子可以包含任意數量的元素。 例如,下圖顯示一個包含 5 個元素 ABCDE 的 7 個桶子的 boost::unordered_set(這只是為了說明,容器通常會有更多桶子)。

buckets

為了決定將元素放置在哪個桶子中,容器將雜湊函數 Hash 應用於元素的鍵(對於 set,鍵是整個元素,但稱為鍵,以便將相同的術語用於 set 和 map)。 這會傳回 std::size_t 型別的值。 std::size_t 的值範圍遠大於桶子的數量,因此容器會對該值應用另一個轉換,以選擇將元素放置在其中的桶子。

擷取給定鍵的元素很簡單。 將相同的程序應用於鍵以找到正確的桶子。 然後將鍵與桶子中的元素進行比較,以找到任何符合的元素(使用相等謂詞 Pred)。 如果雜湊函數運作良好,則元素將均勻分佈在各個桶子之間,因此只需要檢查少量元素。

在下一個章節中,有更多關於雜湊函數和相等謂詞的資訊

您可以在圖表中看到 AD 已放置在同一個桶子中。 當在此桶子中尋找元素時,最多進行 2 次比較,使得搜尋速度較慢。 這稱為碰撞。 為了保持快速,我們嘗試將碰撞降至最低。

如果我們改為使用 boost::unordered_flat_set,而不是 boost::unordered_set,則圖表如下所示

buckets oa

在開放定址容器中,桶子最多可以容納一個元素;如果發生碰撞(例如範例中的 D),則該元素會使用原始位置附近的某個其他可用桶子。 鑑於這種更簡單的情境,Boost.Unordered 開放定址容器提供了一個非常有限的 API 來存取桶子。

表 2. 存取桶子的方法

所有容器

方法

描述

size_type bucket_count() const

桶子的數量。

僅限封閉定址容器

方法

描述

size_type max_bucket_count() const

桶子數量的上限。

size_type bucket_size(size_type n) const

桶子 n 中的元素數量。

size_type bucket(key_type const& k) const

傳回將包含 k 的桶子的索引。

local_iterator begin(size_type n)

傳回桶子 n 的起始和結束迭代器。

local_iterator end(size_type n)

const_local_iterator begin(size_type n) const

const_local_iterator end(size_type n) const

const_local_iterator cbegin(size_type n) const

const_local_iterator cend(size_type n) const

控制桶子的數量

當更多元素加入到無序關聯容器時,碰撞次數會增加,導致效能下降。為了避免這種情況,容器會在插入元素時增加儲存桶(bucket)的數量。您也可以透過呼叫 rehash 來告知容器變更儲存桶的數量(如果需要)。

標準規範給予實作者很大的自由度來決定如何選擇儲存桶的數量,但它確實基於容器的負載因子(load factor)做了一些要求,負載因子是指元素數量除以儲存桶數量。容器也有一個最大負載因子(maximum load factor),它們應該盡量保持負載因子低於這個值。

您無法直接控制儲存桶的數量,但有兩種方法可以影響它:

  • 在建構容器或呼叫 rehash 時,指定最少的儲存桶數量。

  • 透過呼叫 max_load_factor 來建議最大負載因子。

max_load_factor 並不讓您自行設定最大負載因子,它只讓您提供一個提示。即便如此,標準實際上並不要求容器對這個值給予太多關注。唯一必須讓負載因子小於最大值的時機是在呼叫 rehash 之後。但大多數實作會嘗試保持元素數量低於最大負載因子,並將最大負載因子設定為與提示相同或接近的值——除非您的提示值過小或過大。

表 3. 控制儲存桶大小的方法

所有容器

方法

描述

X(size_type n)

建構一個至少有 n 個儲存桶的空容器(X 是容器類型)。

X(InputIterator i, InputIterator j, size_type n)

建構一個至少有 n 個儲存桶的空容器,並從範圍 [i, j) 插入元素(X 是容器類型)。

float load_factor() const

每個儲存桶的平均元素數量。

float max_load_factor() const

回傳目前的最大負載因子。

float max_load_factor(float z)

變更容器的最大負載因子,使用 z 作為提示。
開放定址(Open-addressing)和並行容器:此函數不做任何事情:不允許使用者變更最大負載因子。

void rehash(size_type n)

變更儲存桶的數量,使其至少有 n 個儲存桶,並且讓負載因子小於最大負載因子。

僅適用於開放定址和並行容器

方法

描述

size_type max_load() const

回傳重新雜湊(rehash)之前容器中允許的最大元素數量。

關於開放定址和並行容器的 max_load 的說明:最大負載量將會在 rehash 之後或在容器建立時為 (max_load_factor() * bucket_count()),但在高負載情況下刪除元素時可能會稍微減少。例如,如果我們有一個 boost::unordered_flat_map,其 size() 幾乎達到 max_load() 級別,然後刪除 1,000 個元素,則 max_load() 可能會減少大約幾十個元素。這是 Boost.Unordered 在內部為了保持其效能穩定而進行的,在規劃無須重新雜湊的插入時必須將其納入考量。

相等謂詞和雜湊函數

雖然關聯容器使用排序關係來指定元素的儲存方式,但無序關聯容器使用相等述詞和雜湊函數。例如,boost::unordered_map 宣告為:

template <
    class Key, class Mapped,
    class Hash = boost::hash<Key>,
    class Pred = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class unordered_map;

雜湊函數優先出現,因為您可能只想變更雜湊函數,而不變更相等述詞。例如,如果您想使用 FNV-1a 雜湊,您可以寫:

boost::unordered_map<std::string, int, hash::fnv_1a>
    dictionary;

在 examples 目錄中有 FNV-1a 的實作

如果您希望使用不同的相等函數,您也需要使用匹配的雜湊函數。例如,要實作一個不區分大小寫的字典,您需要定義一個不區分大小寫的相等述詞和雜湊函數:

struct iequal_to
{
    bool operator()(std::string const& x,
        std::string const& y) const
    {
        return boost::algorithm::iequals(x, y, std::locale());
    }
};

struct ihash
{
    std::size_t operator()(std::string const& x) const
    {
        std::size_t seed = 0;
        std::locale locale;

        for(std::string::const_iterator it = x.begin();
            it != x.end(); ++it)
        {
            boost::hash_combine(seed, std::toupper(*it, locale));
        }

        return seed;
    }
};

然後您就可以在不區分大小寫的字典中使用它:

boost::unordered_map<std::string, int, ihash, iequal_to>
    idictionary;

這是 /libs/unordered/examples/case_insensitive.hpp 中範例的簡化版本,該範例支援其他地區設定和字串類型。

注意
使用自訂的相等述詞時,請小心使用相等運算子(==),尤其是當您使用函式指標時。如果您比較兩個具有不同相等述詞的容器,則結果未定義。對於大多數無狀態的函數物件來說,這是不可能的——因為您只能比較具有相同相等述詞的物件,您知道這些相等述詞必須相等。但是,如果您使用函式指標或有狀態的相等述詞(例如,boost::function),則可能會遇到麻煩。

自訂型別

同樣地,自訂類型可以使用自訂雜湊函數:

struct point {
    int x;
    int y;
};

bool operator==(point const& p1, point const& p2)
{
    return p1.x == p2.x && p1.y == p2.y;
}

struct point_hash
{
    std::size_t operator()(point const& p) const
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, p.x);
        boost::hash_combine(seed, p.y);
        return seed;
    }
};

boost::unordered_multiset<point, point_hash> points;

由於預設雜湊函數是 Boost.Hash,我們可以擴充它來支援該類型,以便不需要明確給出雜湊函數:

struct point {
    int x;
    int y;
};

bool operator==(point const& p1, point const& p2)
{
    return p1.x == p2.x && p1.y == p2.y;
}

std::size_t hash_value(point const& p) {
    std::size_t seed = 0;
    boost::hash_combine(seed, p.x);
    boost::hash_combine(seed, p.y);
    return seed;
}

// Now the default function objects work.
boost::unordered_multiset<point> points;

請參閱 Boost.Hash 文件 以取得更多關於如何執行此操作的詳細資訊。請記住,它依賴於對標準的擴充——因此它不適用於無序關聯容器的其他實作,您需要明確地使用 Boost.Hash。

表 4. 存取雜湊和相等函數的方法
方法 描述

hasher hash_function() const

回傳容器的雜湊函數。

key_equal key_eq() const

回傳容器的鍵相等函數。

一般容器

Boost.Unordered 的閉合定址(closed-addressing)容器 (boost::unordered_setboost::unordered_mapboost::unordered_multisetboost::unordered_multimap) 完全符合 C++ 針對無序關聯容器的規範,因此,對於那些知道如何使用 std::unordered_setstd::unordered_map 等的人來說,它們在 Boost.Unordered 中的同名容器是可以直接替換的。開放定址容器 (boost::unordered_node_setboost::unordered_node_mapboost::unordered_flat_setboost::unordered_flat_map) 的介面非常相似,但它們在專用的標準相容性章節中列出了一些細微的差異。

對於沒有使用雜湊容器經驗但熟悉一般關聯容器(std::setstd::mapstd::multisetstd::multimap)的讀者來說,Boost.Unordered 容器的使用方式類似:

typedef boost::unordered_map<std::string, int> map;
map x;
x["one"] = 1;
x["two"] = 2;
x["three"] = 3;

assert(x.at("one") == 1);
assert(x.find("missing") == x.end());

但由於元素沒有排序,因此

for(const map::value_type& i: x) {
    std::cout<<i.first<<","<<i.second<<"\n";
}

的輸出可以是任何順序。例如,它可能是:

two,2
one,1
three,3

還有其他差異,這些差異列在與關聯容器的比較章節中。

迭代器失效

除了 rehashreserve 之外,未指定其他成員函數如何影響儲存桶的數量,儘管當插入導致容器負載大於允許的最大值時,insert 只能使迭代器失效。對於大多數實作來說,這表示 insert 只有在發生這種情況時才會變更儲存桶的數量。迭代器可能會因呼叫 insertrehashreserve 而失效。

至於指標和參考,它們永遠不會對基於節點的容器(boost::unordered_[multi]setboost::unordered_[multi]mapboost::unordered_node_setboost::unordered_node_map)失效,但當為 boost::unordered_flat_setboost::unordered_flat_map 發生重新雜湊時,它們將會失效:這是因為這些容器將元素直接儲存在它們的保存儲存桶中,因此在配置新的儲存桶陣列時,必須透過移動建構來傳輸元素。

以類似於對 vector 使用 reserve 的方式,在插入大量元素之前呼叫 reserve 可能是一個好主意。這會將昂貴的重新雜湊排除在外,並讓您儲存迭代器,並確保它們不會失效。如果要將 n 個元素插入容器 x 中,您可以先呼叫:

x.reserve(n);
注意

reserve(n) 為至少 n 個元素保留空間,分配足夠的儲存桶,以便不超過最大負載因子。

由於最大負載因子定義為元素數量除以可用儲存桶總數,因此此函數在邏輯上等同於:

x.rehash(std::ceil(n / x.max_load_factor()))

請參閱關於 rehash 函數的參考資料以取得更多詳細資訊

與關聯式容器比較

表 5. 介面差異
關聯容器 無序關聯容器

由排序關係 Compare 參數化

由函數物件 Hash 和等價關係 Pred 參數化

可以使用 key_compare 來比較鍵,可以使用成員函數 key_comp() 存取該 key_compare,可以使用 value_compare 來比較值,可以使用成員函數 value_comp() 存取該 value_compare

可以使用 hasher 來雜湊鍵,可以使用成員函數 hash_function() 存取該 hasher,可以使用 key_equal 來檢查鍵的相等性,可以使用成員函數 key_eq() 存取該 key_equal。沒有用於比較或雜湊值的函數物件。

建構子具有比較物件的可選額外參數。

建構子具有初始最小儲存桶數量、雜湊函數和相等物件的可選額外參數。

如果 !Compare(k1, k2) && !Compare(k2, k1),則鍵 k1k2 被視為相等。

如果 Pred(k1, k2),則鍵 k1k2 被視為相等。

成員函數 lower_bound(k)upper_bound(k)

沒有等效的成員函數。由於元素沒有排序,lower_boundupper_bound 將毫無意義。

如果容器中不存在 kequal_range(k) 會在 k 將被插入的位置回傳一個空範圍。

如果容器中不存在 kequal_range(k) 會在容器的末尾回傳一個範圍。它無法回傳定位的範圍,因為 k 可以插入到多個位置。
閉合定址容器:若要找出 k 將被插入的儲存桶,請使用 bucket(k)。但請記住,插入可能會導致容器重新雜湊——這表示元素可以插入到不同的儲存桶中。

iteratorconst_iterator 屬於雙向類別。

iteratorconst_iterator 至少屬於前向類別。

迭代器、指標和對容器元素的參考永遠不會失效。

迭代器可能會因呼叫插入或重新雜湊而失效。.
基於節點的容器:指標和對容器元素的參考永遠不會失效。
扁平容器:當發生重新雜湊時,指標和對容器元素的參考將會失效。

迭代器按照比較物件定義的順序遍歷容器。

迭代器以任意順序遍歷容器,該順序可能會隨著元素的插入而變更,儘管相等的元素總是相鄰。

沒有等效的成員函數

閉合定址容器:可以使用本機迭代器遍歷個別儲存桶。(本機迭代器和迭代器的順序不要求具有任何對應關係。)

可以使用 ==!=<<=>>= 運算子進行比較。

可以使用 ==!= 運算子進行比較。

當插入帶有提示的元素時,實作可以忽略提示。


表 6. 複雜度保證
操作 關聯容器 無序關聯容器

建構空容器

常數時間

O(n),其中 n 是最小儲存桶數量。

N 個元素的範圍建構容器

O(N log N),如果範圍以 value_comp() 排序,則為 O(N)

平均情況 O(N),最差情況 O(N2)

插入單個元素

對數時間

平均情況常數時間,最差情況線性時間

插入帶有提示的單個元素

如果 t 個元素在提示後立即插入,則為攤還常數時間,否則為對數時間

平均情況常數時間,最差情況線性時間(即與一般插入相同)。

插入 N 個元素的範圍

N log(size() + N)

平均情況 O(N),最差情況 O(N * size())

依鍵 k 刪除

O(log(size()) + count(k))

平均情況:O(count(k)),最差情況:O(size())

透過迭代器刪除單一元素

均攤常數時間

平均情況:O(1),最差情況:O(size())

刪除 N 個元素的範圍

O(log(size()) + N)

平均情況:O(N),最差情況:O(size())

清除容器

O(size())

O(size())

尋找

對數時間

平均情況:O(1),最差情況:O(size())

計數

O(log(size()) + count(k))

平均情況:O(1),最差情況:O(size())

equal_range(k)

對數時間

平均情況:O(count(k)),最差情況:O(size())

lower_bound,upper_bound

對數時間

不適用

並行容器

Boost.Unordered 提供了 boost::concurrent_node_setboost::concurrent_node_mapboost::concurrent_flat_setboost::concurrent_flat_map,這些雜湊表允許來自不同執行緒的並行寫入/讀取存取,而無需在使用者端實作任何同步機制。

std::vector<int>                    input;
boost::concurrent_flat_map<int,int> m;

...

// process input in parallel
const int                 num_threads = 8;
std::vector<std::jthread> threads;
std::size_t               chunk = input.size() / num_threads; // how many elements per thread

for (int i = 0; i < num_threads; ++i) {
  threads.emplace_back([&,i] {
    // calculate the portion of input this thread takes care of
    std::size_t start = i * chunk;
    std::size_t end = (i == num_threads - 1)? input.size(): (i + 1) * chunk;

    for (std::size_t n = start; n < end; ++n) {
      m.emplace(input[n], calculation(input[n]));
    }
  });
}

在上面的範例中,執行緒存取 m 時沒有同步,就像在單執行緒情境中一樣。在理想情況下,如果給定的工作負載分佈在 N 個執行緒之間,則執行速度比一個執行緒快 N 倍——由於同步開銷和競爭(一個執行緒等待另一個執行緒離開地圖的鎖定部分),實際上永遠無法達到此限制,但 Boost.Unordered 並行容器的設計使其執行時的開銷非常小,並且通常實現線性擴展(也就是說,效能與執行緒數量成正比,直到 CPU 中的邏輯核心數量)。

基於訪問的 API

Boost.Unordered 並行容器的新使用者首先會注意到這些類別不提供迭代器(這使得它們在技術上不是 C++ 標準意義上的 容器)。原因在於迭代器本質上是執行緒不安全的。考慮以下假設程式碼

auto it = m.find(k);  // A: get an iterator pointing to the element with key k
if (it != m.end() ) {
  some_function(*it); // B: use the value of the element
}

在多執行緒情境中,如果其他執行緒在 A 和 B 之間發出 m.erase(k) 操作,則迭代器 it 在 B 點可能會失效。有些設計可以透過讓迭代器鎖定它們指向的元素來解決這個問題,但這種方法容易產生高度競爭,並且很容易在程式中產生死鎖。operator[] 也有類似的並行問題,boost::concurrent_flat_map/boost::concurrent_node_map 也不提供此功能。相反地,元素存取是透過所謂的訪問函數來完成的

m.visit(k, [](const auto& x) { // x is the element with key k (if it exists)
  some_function(x);            // use it
});

使用者傳遞的訪問函數(在此案例中為 lambda 函數)由 Boost.Unordered 在內部以執行緒安全的方式執行,因此它可以存取元素,而無需擔心其他執行緒干擾該過程。

另一方面,訪問函數無法存取容器本身

m.visit(k, [&](const auto& x) {
  some_function(x, m.size()); // forbidden: m can't be accessed inside visitation
});

允許存取不同的容器

m.visit(k, [&](const auto& x) {
  if (some_function(x)) {
    m2.insert(x); // OK, m2 is a different boost::concurrent_flat_map
  }
});

但總體而言,訪問函數應盡可能輕量,以減少競爭並增加並行化。在某些情況下,將繁重的工作移出訪問可能是有益的

std::optional<value_type> o;
bool found = m.visit(k, [&](const auto& x) {
  o = x;
});
if (found) {
  some_heavy_duty_function(*o);
}

訪問在並行容器提供的 API 中非常突出,許多經典操作都有啟用訪問的版本

m.insert_or_visit(x, [](auto& y) {
  // if insertion failed because of an equivalent element y,
  // do something with it, for instance:
  ++y.second; // increment the mapped part of the element
});

請注意,在最後一個範例中,訪問函數實際上可以修改元素:作為一般規則,對並行地圖 m 的操作將根據 m 是 const/non-const 來授予訪問函數對元素的 const/non-const 存取權。可以透過使用 cvisit 多載(例如,insert_or_cvisit)來始終明確請求 const 存取,並且可能會導致更高的並行化。另一方面,對於並行集合,訪問始終是 const 存取。

雖然預計使用頻率會低得多,但並行容器還提供插入操作,其中元素可以在元素建立後立即被訪問(除了當已經存在等效元素時的通常訪問之外)

  m.insert_and_cvisit(x,
    [](const auto& y) {
      std::cout<< "(" << y.first << ", " << y.second <<") inserted\n";
    },
    [](const auto& y) {
      std::cout<< "(" << y.first << ", " << y.second << ") already exists\n";
    });

有關啟用訪問操作的完整列表,請參閱 boost::concurrent_node_setboost::concurrent_node_mapboost::concurrent_flat_setboost::concurrent_flat_map 的參考資料。

全表訪問

在沒有迭代器的情況下,visit_all 作為另一種處理容器中所有元素的方法提供

m.visit_all([](auto& x) {
  x.second = 0; // reset the mapped part of the element
});

在實作標準並行演算法的 C++17 編譯器中,整個表格的訪問可以並行化

m.visit_all(std::execution::par, [](auto& x) { // run in parallel
  x.second = 0; // reset the mapped part of the element
});

遍歷可以在中途被中斷

// finds the key to a given (unique) value

int  key = 0;
int  value = ...;
bool found = !m.visit_while([&](const auto& x) {
  if(x.second == value) {
    key = x.first;
    return false; // finish
  }
  else {
    return true;  // keep on visiting
  }
});

if(found) { ... }

還有最後一個整個表格的訪問操作,erase_if

m.erase_if([](auto& x) {
  return x.second == 0; // erase the elements whose mapped value is zero
});

visit_whileerase_if 也可以並行化。請注意,為了提高效率,整個表格的訪問操作在執行期間不會鎖定表格:這意味著元素可能會在訪問期間被其他執行緒插入、修改或刪除。建議不要對程式中任何時間點並行容器的確切全域狀態做過多的假設。

批量訪問

假設您有一個要同時在並行地圖中查找的鍵的 std::array

std::array<int, N> keys;
...
for(const auto& key: keys) {
  m.visit(key, [](auto& x) { ++x.second; });
}

批量訪問允許我們在一個操作中傳遞所有鍵

m.visit(keys.begin(), keys.end(), [](auto& x) { ++x.second; });

雖然此功能並非僅為語法上的方便而提供:透過一次處理所有鍵,可以應用一些內部最佳化,與常規的逐一處理相比,可以提高效能(請參閱 基準測試)。實際上,緩衝傳入的鍵,以便它們可以分塊批量訪問可能是有益的

static constexpr auto bulk_visit_size = boost::concurrent_flat_map<int,int>::bulk_visit_size;
std::array<int, bulk_visit_size> buffer;
std::size_t                      i=0;
while(...) { // processing loop
  ...
  buffer[i++] = k;
  if(i == bulk_visit_size) {
    map.visit(buffer.begin(), buffer.end(), [](auto& x) { ++x.second; });
    i = 0;
  }
  ...
}
// flush remaining keys
map.visit(buffer.begin(), buffer.begin() + i, [](auto& x) { ++x.second; });

這裡存在延遲/吞吐量的權衡:處理傳入的鍵需要更長的時間(因為它們被緩衝了),但每秒處理的鍵數量會更高。bulk_visit_size 是建議的區塊大小 — 較小的緩衝區可能會導致效能更差。

阻塞操作

並行容器可以像任何其他 Boost.Unordered 容器一樣進行複製、指派、清除和合併。與大多數其他操作不同,這些是阻塞的,也就是說,在複製、指派、清除或合併操作正在進行時,會阻止所有其他執行緒存取相關的表格。阻塞由函式庫自動處理,使用者無需採取任何特殊預防措施,但整體效能可能會受到影響。

另一個阻塞操作是重新雜湊,它透過 rehash/reserve 明確發生,或在表格的負載達到 max_load() 時在插入期間發生。與非並行容器一樣,在批量插入之前預留空間通常會加快處理速度。

與非並行容器的互通性

由於開放尋址和並行容器基於相同的內部資料結構,它們可以從非並行對應物有效地移動建構,反之亦然。

表 7. 並行/非並行互操作性

boost::concurrent_node_set

boost::unordered_node_set

boost::concurrent_node_map

boost::unordered_node_map

boost::concurrent_flat_set

boost::unordered_flat_set

boost::concurrent_flat_map

boost::unordered_flat_map

此互操作性在多階段情境中很方便,其中部分資料處理並行發生,而其他步驟是非並行(或非修改)的。在以下範例中,我們想要從大量的輸入字詞向量中建構直方圖:填充階段可以使用 boost::concurrent_flat_map 並行完成,然後將結果傳輸到最終容器。

std::vector<std::string> words = ...;

// Insert words in parallel
boost::concurrent_flat_map<std::string_view, std::size_t> m0;
std::for_each(
  std::execution::par, words.begin(), words.end(),
  [&](const auto& word) {
    m0.try_emplace_or_visit(word, 1, [](auto& x) { ++x.second; });
  });

// Transfer to a regular unordered_flat_map
boost::unordered_flat_map m=std::move(m0);

雜湊品質

為了正常工作,雜湊表要求提供的雜湊函數具有良好的品質,大致意味著它會盡可能均勻地使用其 std::size_t 輸出空間,就像亂數產生器一樣—當然,雜湊函數的值不是隨機的,而是嚴格由其輸入參數決定的。

Boost.Unordered 中的封閉尋址容器對於品質不太理想的雜湊函數具有相當的穩健性,但開放尋址和並行容器對此因素更敏感,如果雜湊函數不適當,其效能可能會大幅降低。通常,如果您使用 Boost.Hash 提供或產生的函數,則品質將是足夠的,但在使用替代雜湊演算法時,您必須小心。

本節的其餘部分僅適用於開放尋址和並行容器。

雜湊後混淆和雪崩效應

即使您提供的雜湊函數不符合開放尋址所需的均勻行為,Boost.Unordered 容器的效能也可能可以接受,因為函式庫會執行內部後混合步驟,以改善計算的雜湊值的統計屬性。這會帶來額外的計算成本;如果您想選擇退出後混合,請按如下方式註解您的雜湊函數

struct my_string_hash_function
{
  using is_avalanching = std::true_type; // instruct Boost.Unordered to not use post-mixing

  std::size_t operator()(const std::string& x) const
  {
    ...
  }
};

透過設定 hash_is_avalanching 特徵,我們通知 Boost.Unordered my_string_hash_function 的品質足以直接使用,而無需任何後混合安全網。如果雜湊函數的行為不如我們宣告的那樣良好,這會帶來效能降低的風險。

容器統計資訊

如果我們全域定義巨集 BOOST_UNORDERED_ENABLE_STATS,則開放尋址和並行容器將計算一些與雜湊函數品質直接相關的內部統計資料

#define BOOST_UNORDERED_ENABLE_STATS
#include <boost/unordered/unordered_map.hpp>

...

int main()
{
  boost::unordered_flat_map<std::string, int, my_string_hash> m;
  ... // use m

  auto stats = m.get_stats();
  ... // inspect stats
}

stats 物件提供以下資訊

stats
     .insertion                                     // Insertion operations
               .count                               // Number of operations
               .probe_length                        // Probe length per operation
                            .average
                            .variance
                            .deviation
	 .successful_lookup                             // Lookup operations (element found)
                       .count                       // Number of operations
                       .probe_length                // Probe length per operation
                                    .average
                                    .variance
                                    .deviation
                       .num_comparisons             // Elements compared per operation
			                           .average
                                       .variance
                                       .deviation
	 .unsuccessful_lookup                           // Lookup operations (element not found)
                         .count                     // Number of operations
                         .probe_length              // Probe length per operation
                                      .average
                                      .variance
                                      .deviation
                         .num_comparisons           // Elements compared per operation
			                             .average
                                         .variance
                                         .deviation

維護三個內部操作的統計資料:插入(不考慮先前判斷鍵尚未存在的查找)、成功查找和不成功查找(包括插入元素時在內部發出的查找)。探測長度是每個操作存取的 儲存桶群組 的數量。如果雜湊函數行為正常

  • 平均探測長度應接近 1.0。

  • 每次成功查找的平均比較次數應接近 1.0(也就是說,只檢查找到的元素)。

  • 每次不成功查找的平均比較次數應接近 0.0。

提供一個 範例,顯示 boost::hash<std::string> 的容器統計資料,它是 FNV-1a 雜湊的實作,以及兩個行為不佳的自訂雜湊函數,它們已被錯誤地標記為雪崩式。

                   boost::unordered_flat_map:   319 ms
                                   insertion: probe length 1.08771
                           successful lookup: probe length 1.06206, num comparisons 1.02121
                         unsuccessful lookup: probe length 1.12301, num comparisons 0.0388251

           boost::unordered_flat_map, FNV-1a:   301 ms
                                   insertion: probe length 1.09567
                           successful lookup: probe length 1.06202, num comparisons 1.0227
                         unsuccessful lookup: probe length 1.12195, num comparisons 0.040527

boost::unordered_flat_map, slightly_bad_hash:   654 ms
                                   insertion: probe length 1.03443
                           successful lookup: probe length 1.04137, num comparisons 6.22152
                         unsuccessful lookup: probe length 1.29334, num comparisons 11.0335

         boost::unordered_flat_map, bad_hash: 12216 ms
                                   insertion: probe length 699.218
                           successful lookup: probe length 590.183, num comparisons 43.4886
                         unsuccessful lookup: probe length 1361.65, num comparisons 75.238

標準相容性

封閉定址容器

boost::unordered_[multi]setboost::unordered_[multi]map 為 C++11(或更高版本)編譯器提供最新標準修訂版本的 C++ 無序關聯容器的符合實作,並具有如所述的非常小的偏差。這些容器完全符合 AllocatorAware,並且支援 花俏指標

推導指引

僅在 C++17(或更高版本)編譯器上提供 類別範本引數推導 (CTAD) 的推導指南。

逐片配對就位

依照標準規範,boost::unordered_[multi]map::emplace 支援逐段建構配對 (piecewise pair construction)。

boost::unordered_multimap<std::string, std::complex> x;

x.emplace(
    std::piecewise_construct,
    std::make_tuple("key"), std::make_tuple(1, 2));

此外,相同的函式功能透過非標準的 boost::unordered::piecewise_construct 和 Boost.Tuple 提供。

x.emplace(
    boost::unordered::piecewise_construct,
    boost::make_tuple("key"), boost::make_tuple(1, 2));

為了與舊版的 Boost.Unordered 回溯相容,此功能被保留下來:我們鼓勵使用者將程式碼更新為使用 std::piecewise_constructstd::tuple

交換

當進行交換時,PredHash 目前並非透過呼叫 swap 來交換,而是使用其複製建構函式。因此,當進行交換時,可能會從其複製建構函式中擲出例外。

開放定址容器

C++ 標準目前未提供任何開放定址容器的規範可供遵循,因此 boost::unordered_flat_set/unordered_node_setboost::unordered_flat_map/unordered_node_map 分別從 std::unordered_setstd::unordered_map 中汲取靈感,並在方便或受到其內部資料結構指示時,會偏離它們的介面,因為它們的內部資料結構與標準(封閉定址)所規定的截然不同。

Boost.Unordered 提供的開放定址容器僅適用於相當符合 C++11(或更新版本)的編譯器。移動語意和可變參數範本參數等語言層級的功能則不進行模擬。這些容器完全 AllocatorAware,並支援花式指標

與 C++ 無序關聯式容器的主要差異在於

  • 一般而言

    • begin() 不是常數時間。

    • erase(iterator) 不會傳回指向下一個元素的迭代器,而是傳回一個代理物件,該物件在被要求時會轉換為該迭代器;這可以避免在不需要時進行潛在的高成本迭代器遞增操作。

    • 沒有用於儲存桶處理的 API(除了 bucket_count)。

    • 容器的最大載入因子由內部管理,使用者無法設定。透過公開函式 max_load 公開的最大載入量,可能會在高載入條件下因刪除而減少。

  • 平面容器 (boost::unordered_flat_setboost::unordered_flat_map)

    • value_type 必須是可移動建構的。

    • 指標穩定性在重新雜湊時不會保持。

    • 沒有用於節點擷取/插入的 API。

並行容器

C++ 標準目前沒有針對此或任何其他類型的並行資料結構的規範。boost::concurrent_flat_set/boost::concurrent_node_setboost::concurrent_flat_map/boost::concurrent_node_map 的 API 分別模仿 std::unordered_flat_setstd::unordered_flat_map,但關鍵的差異在於,由於迭代器在並行情境中存在固有問題(高競爭、容易死鎖),因此不提供迭代器:因此,Boost.Unordered 並行容器在技術上不是 Container 的模型,儘管它們滿足 AllocatorAware 容器的所有要求(包括花式指標支援),但那些隱含迭代器的要求除外。

在非並行的無序容器中,迭代器有兩個主要用途

  • 存取先前透過查詢定位的元素。

  • 容器遍歷。

Boost.Unordered 並行容器使用*內部訪問*工具作為執行緒安全的替代方案,而不是使用迭代器。將傳回指向容器中已存在之元素的迭代器的傳統操作,例如

iterator find(const key_type& k);
std::pair<iterator, bool> insert(const value_type& obj);

被轉換為接受一個*訪問函式*,該函式會傳遞此元素

template<class F> size_t visit(const key_type& k, F f);
template<class F> bool insert_or_visit(const value_type& obj, F f);

(在第二種情況下,只有當表格中有與 obj 等效的元素時才會呼叫 f,如果插入成功則不會呼叫)。容器遍歷由以下功能提供

template<class F> size_t visit_all(F f);

其中在支援並行演算法的 C++17 編譯器中具有並行版本。一般而言,並行容器的介面是從其非並行對應項目的介面衍生而來,方法是將迭代器替換為適用時的訪問。如果對於常規映射,iteratorconst_iterator 分別提供對元素的可變和 const 存取,則此處的訪問取決於所使用成員函式的常數性而授予可變或 const 存取(也有用於明確 const 訪問的 *cvisit 多載);在 boost::concurrent_flat_set 的情況下,訪問始終是 const。

boost::concurrent_flat_map/boost::concurrent_node_map 未提供的其中一個值得注意的操作是 operator[]/at,如果以更複雜的方式,可以使用 try_emplace_or_visit 取代。

資料結構

封閉定址容器

Boost.Unordered 擁有最快的封閉定址實作之一,也稱為分離鏈接。以下是表示資料結構的範例圖

bucket groups
圖 1. 簡單的儲存桶群組方法

分配一個「儲存桶」陣列,每個儲存桶又指向其各自的連結串列。這使得滿足儲存桶迭代的標準要求變得簡單。不幸的是,使用此佈局時,整個容器的迭代通常很慢,因為必須檢查每個儲存桶的佔用情況,當標準要求複雜度為 O(size()) 時,會產生 O(bucket_count() + size()) 的時間複雜度。

標準實現的規範會如下圖所示

singly linked
圖 2. 規範的標準方法

值得注意的是,此方法僅由 libc++ 和 libstdc++ 使用;MSVC Dinkumware 實作使用不同的方法。可以在這裡找到對標準容器的更詳細分析。

選擇此不尋常的佈局資料結構是為了透過將所有節點互連到單向連結串列中,使整個容器的迭代更有效率。人們可能還會注意到,儲存桶指向儲存桶元素*之前*的節點。這樣做是為了可以有效地從列表中刪除元素,而無需引入雙向連結串列。不幸的是,此資料結構引入了有保證的額外間接。例如,要存取儲存桶的第一個元素,必須執行如下操作

auto const idx = get_bucket_idx(hash_function(key));
node* p = buckets[idx]; // first load
node* n = p->next; // second load
if (n && is_in_bucket(n, idx)) {
  value_type const& v = *n; // third load
  // ...
}

使用簡單的儲存桶群組佈局,只需執行以下操作即可

auto const idx = get_bucket_idx(hash_function(key));
node* n = buckets[idx]; // first load
if (n) {
  value_type const& v = *n; // second load
  // ...
}

實際上,額外的間接可能會對 insertfinderase 等常見操作產生顯著的效能影響。但是為了使容器的迭代快速,Boost.Unordered 引入了一個新的資料結構,「儲存桶群組」。儲存桶群組是儲存桶陣列子區段的固定寬度檢視。它包含一個位元遮罩 (std::size_t),用於追蹤儲存桶的佔用情況,並包含兩個指標,以便它可以與非空群組形成雙向連結串列。以下是一個範例圖

fca
圖 3. Boost 使用的新佈局

因此,全容器迭代被轉換為遍歷非空儲存桶群組(常數時間複雜度的操作),從而將時間複雜度降回 O(size())。總而言之,儲存桶群組的大小僅為 4 個字,並且它可以檢視 sizeof(std::size_t) * CHAR_BIT 個儲存桶,這表示對於所有常見的實作,每個儲存桶僅引入 4 位元的空間額外負荷。

外部文章中提供了對 Boost.Unordered 封閉定址實作的更詳細說明。有關實作原理的更多資訊,請閱讀對應章節

開放定址容器

該圖顯示了 boost::unordered_flat_set/unordered_node_setboost:unordered_flat_map/unordered_node_map 的基本內部佈局。

foa
圖 4. Boost.Unordered 使用的開放定址佈局。

與所有開放定址容器一樣,元素(或 boost::unordered_node_setboost::unordered_node_map 中的元素節點指標)直接儲存在儲存桶陣列中。此陣列在邏輯上分為 2n 個*群組*,每個群組包含 15 個元素。除了儲存桶陣列之外,還有一個關聯的*元資料陣列*,其中包含 2n 個 16 位元組的字組。

foa metadata
圖 5. 元資料字組的分解。

元資料字組分為 15 個 hi 位元組(每個關聯的儲存桶一個),以及一個溢位位元組(圖中的 ofw)。hi 的值為

  • 如果對應的儲存桶為空,則為 0。

  • 1 用於編碼稱為哨兵的特殊空儲存桶,該儲存桶在內部使用,以便在容器完全遍歷時停止迭代。

  • 如果儲存桶已被佔用,則為從元素的雜湊值取得的簡化雜湊值

當尋找雜湊值為 h 的元素時,諸如 SSE2Neon 之類的 SIMD 技術可讓我們非常快速地檢查完整的元資料字組,並僅使用少數幾個 CPU 指令在所有 15 個儲存桶中尋找 h 的簡化值:可以輕易地捨棄不匹配的儲存桶,並且需要透過與對應元素進行完整比較來檢查簡化雜湊值匹配的儲存桶。如果尋找的元素不存在,則檢查溢位位元組

  • 如果位置 h mod 8 中的位元為零,則查詢終止(且該元素不存在)。

  • 如果該位元設定為 1(群組已溢位),則使用二次探測檢查其他群組,然後重複該過程。

插入在演算法上類似:使用 SIMD 定位空的儲存桶,當經過完整的群組時,其對應的溢位位元會設定為 1。

在沒有 SIMD 支援的架構中,邏輯佈局保持不變,但元資料字組使用我們稱之為位元交錯的技術進行編碼:此佈局允許我們僅使用標準算術和邏輯運算來模擬 SIMD,並具有相當良好的效能。

foa metadata interleaving
圖 6. 位元交錯的元資料字組。

外部文章中提供了對 Boost.Unordered 開放定址實作的更詳細說明。有關實作原理的更多資訊,請閱讀對應章節

並行容器

boost::concurrent_flat_set/boost::concurrent_node_setboost::concurrent_flat_map/boost::concurrent_node_map 使用上述基本的開放定址配置,並輔以同步機制。

cfoa
圖 7. Boost.Unordered 使用的並行開放定址配置。

使用兩個層級的同步機制

  • 容器層級:使用讀寫互斥鎖來控制任何操作對容器的存取。通常,即使是修改操作,此存取也是以讀取模式(即並行)進行,因此在大多數實際應用中,此層級沒有執行緒爭用。只有在重新雜湊或執行容器範圍的操作(例如交換或賦值)時,存取才會以寫入模式(阻塞)進行。

  • 群組層級:每個 15 個槽位的群組都配有一個包含以下內容的 8 位元組字組:

    • 一個讀寫自旋鎖,用於同步存取群組中的任何元素。

    • 一個原子插入計數器,用於如下所述的樂觀插入。

透過使用原子操作存取群組中繼資料,在需要與先前已進行 SIMD 比對的元素進行實際比較之前,查詢是(群組層級)無鎖的:只有在那時才會使用群組的自旋鎖。

插入使用以下樂觀演算法

  • 探測序列中初始群組的插入計數器值會被局部記錄(我們將此值稱為 c0)。

  • 查詢如上所述。如果查詢找不到等效元素,則搜尋可用的插入槽位,並依序鎖定/解鎖探測序列中的每個群組。

  • 當找到可用的槽位時,它會被搶佔式佔用(其縮減的雜湊值會被設定),並且插入計數器會以原子方式遞增:如果在整個操作過程中沒有其他執行緒遞增計數器(這會透過與 c0 比較來檢查),那麼我們就可以完成插入,否則我們會回滾並重新開始。

此演算法在查詢和實際插入階段都具有非常低的爭用,但如果其他執行緒干擾並在同一群組開始執行成功的插入,則可能需要重新開始計算。實際上,重新開始的頻率非常小,在我們的某些基準測試中,測得的頻率為百萬分之幾。

有關實作原理的更多資訊,請閱讀相應章節

可除錯性

Visual Studio Natvis

所有容器和迭代器在 Natvis 框架中都有自訂視覺化效果。

在你的專案中使用

若要在您的專案中於 Natvis 框架中視覺化 Boost.Unordered 容器,只需將檔案 /extra/boost_unordered.natvis 作為「現有項目」新增至您的 Visual Studio 專案。

視覺化結構

視覺化效果會鏡射標準無序容器的視覺化效果。容器一次最多顯示 100 個元素。每個集合元素的項目名稱都列為 [i],其中 i 是顯示中的索引,從 0 開始。每個映射元素的項目名稱預設都列為 [{key-display}]。例如,如果第一個元素是配對 ("abc", 1),則項目名稱將為 ["abc"]。可以使用檢視「ShowElementsByIndex」來覆寫此行為,該檢視會將映射顯示行為切換為按索引命名元素。此相同的檢視名稱也用於標準無序容器中。

預設情況下,封閉定址容器將顯示 [hash_function][key_eq][spare_hash_function][spare_key_eq](如果適用)、[allocator] 和元素。使用檢視「detailed」會新增 [bucket_count][max_load_factor]。相反地,使用檢視「simple」只會顯示元素,而不顯示其他項目。

預設情況下,開放定址容器將顯示 [hash_function][key_eq][allocator] 和元素。使用檢視「simple」只會顯示元素,而不顯示其他項目。SIMD 和非 SIMD 實作都可以透過 Natvis 框架檢視。

迭代器的顯示方式與其標準對應項類似。迭代器的顯示方式就好像它是其指向的元素一樣。結束迭代器會簡單地顯示為 { end iterator }

花式指標

如果您在配置器中使用花式指標(例如 boost::interprocess::offset_ptr),則容器視覺化效果也有效。雖然這種情況很少見,但 Boost.Unordered 具有 natvis 自訂點,可支援任何類型的花式指標。boost::interprocess::offset_ptr 已在 Boost.Interprocess 程式庫中定義支援,您可以依照檔案 /extra/boost_unordered.natvis 結尾附近的註解中包含的指示,將支援新增至您自己的類型。

GDB 美化列印器

所有容器和迭代器都有自訂的 GDB 美化列印器。

在你的專案中使用

始終在使用美化列印器時,您必須像下面一樣啟用美化列印。這通常是一次性的設定。

(gdb) set print pretty on

預設情況下,如果您編譯成 ELF 二進位格式,則您的二進位檔案將包含 Boost.Unordered 美化列印器。若要使用內嵌的美化列印器,請確保您允許像下面一樣自動載入。每次載入 GDB 時都必須執行此操作,或將其新增至 ".gdbinit" 檔案。

(gdb) add-auto-load-safe-path [/path/to/executable]

您可以選擇嵌入美化列印器來編譯您的二進位檔案,方法是定義 BOOST_ALL_NO_EMBEDDED_GDB_SCRIPTS,這會針對具有此功能的所有 Boost 程式庫停用內嵌的 GDB 美化列印器。

您可以從非內嵌的 Python 腳本外部載入美化列印器。使用如下所示的 source 命令新增腳本 /extra/boost_unordered_printers.py

(gdb) source [/path/to/boost]/libs/unordered/extra/boost_unordered_printers.py

視覺化結構

視覺化效果會鏡射標準無序容器。映射容器會顯示從鍵到映射值的關聯。集合容器會顯示從索引到值的關聯。迭代器會顯示其項目,或顯示為結束迭代器。以下是範例 boost::unordered_map、範例 boost::unordered_set 以及它們各自的開始和結束迭代器可能顯示的內容。

(gdb) print example_unordered_map
$1 = boost::unordered_map with 3 elements = {["C"] = "c", ["B"] = "b", ["A"] = "a"}
(gdb) print example_unordered_map_begin
$2 = iterator = { {first = "C", second = "c"} }
(gdb) print example_unordered_map_end
$3 = iterator = { end iterator }
(gdb) print example_unordered_set
$4 = boost::unordered_set with 3 elements = {[0] = "c", [1] = "b", [2] = "a"}
(gdb) print example_unordered_set_begin
$5 = iterator = { "c" }
(gdb) print example_unordered_set_end
$6 = iterator = { end iterator }

其他容器是相同的,只是在顯示容器本身時,將 "boost::unordered_{map|set}" 替換為適當的樣板名稱。請注意,每個子元素(即鍵、映射值或值)都會根據其自身的列印設定顯示,其中可能包括其自身的美化列印器。

SIMD 和非 SIMD 實作都可以透過 GDB 美化列印器檢視。

對於啟用容器統計資料的開放定址容器,您可以透過在 GDB 內對容器呼叫 get_stats() 來取得這些統計資料。這在 GDB 中會被覆寫為 xmethod,因此它不會叫用任何 C++ 同步程式碼。請參閱以下列印輸出,以取得預期格式的範例。

(gdb) print example_flat_map.get_stats()
$1 = [stats] = {[insertion] = {[count] = 5, [probe_length] = {avg = 1.0, var = 0.0, dev = 0.0}},
  [successful_lookup] = {[count] = 0, [probe_length] = {avg = 0.0, var = 0.0, dev = 0.0},
    [num_comparisons] = {avg = 0.0, var = 0.0, dev = 0.0}}, [unsuccessful_lookup] = {[count] = 5,
    [probe_length] = {avg = 1.0, var = 0.0, dev = 0.0},
    [num_comparisons] = {avg = 0.0, var = 0.0, dev = 0.0}}}

花式指標

如果您在配置器中使用花式指標(例如 boost::interprocess::offset_ptr),則美化列印器也有效。雖然這種情況很少見,但 Boost.Unordered 具有 GDB 美化列印器自訂點,可支援任何類型的花式指標。boost::interprocess::offset_ptr 已在 Boost.Interprocess 程式庫中定義支援,您可以依照檔案 /extra/boost_unordered_printers.py 結尾附近的註解中包含的指示,將支援新增至您自己的類型。

效能基準

boost::unordered_[multi]set

所有基準測試都是使用 unordered_set<unsigned int>(非重複)和 unordered_multiset<unsigned int>(重複)建立的。原始碼可以在這裡找到

插入基準測試會插入 n 個隨機值,其中 n 介於 10,000 到 300 萬之間。對於重複的基準測試,相同的隨機值平均會重複 5 次。

刪除基準測試會隨機刪除所有 n 個元素,直到容器為空。按鍵刪除會使用 erase(const key_type&) 在每個操作中移除整組等效元素。

成功的查詢基準測試是透過以其原始插入順序查詢所有 n 個值來完成的。

不成功的查詢基準測試會使用 n 個隨機產生的整數,但使用不同的種子值。

GCC 12 + libstdc++-v3, x64

插入
running insertion.xlsx.practice
running%20insertion.xlsx.practice non unique
running%20insertion.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

running%20insertion.xlsx.practice norehash
running%20insertion.xlsx.practice norehash non unique
running%20insertion.xlsx.practice norehash non unique 5

非重複元素,
先前 reserve

重複元素,
先前 reserve

重複元素,
最大載入因子 5,
先前 reserve

刪除
scattered%20erasure.xlsx.practice
scattered%20erasure.xlsx.practice non unique
scattered%20erasure.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

scattered%20erasure%20by%20key.xlsx.practice non unique
scattered%20erasure%20by%20key.xlsx.practice non unique 5

按鍵,重複元素

按鍵,重複元素,
最大載入因子 5

成功查詢
scattered%20successful%20looukp.xlsx.practice
scattered%20successful%20looukp.xlsx.practice non unique
scattered%20successful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

不成功查詢
scattered%20unsuccessful%20looukp.xlsx.practice
scattered%20unsuccessful%20looukp.xlsx.practice non unique
scattered%20unsuccessful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

Clang 15 + libc++, x64

插入
running%20insertion.xlsx.practice
running%20insertion.xlsx.practice non unique
running%20insertion.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

running%20insertion.xlsx.practice norehash
running%20insertion.xlsx.practice norehash non unique
running%20insertion.xlsx.practice norehash non unique 5

非重複元素,
先前 reserve

重複元素,
先前 reserve

重複元素,
最大載入因子 5,
先前 reserve

刪除
scattered%20erasure.xlsx.practice
scattered%20erasure.xlsx.practice non unique
scattered%20erasure.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

scattered%20erasure%20by%20key.xlsx.practice non unique
scattered%20erasure%20by%20key.xlsx.practice non unique 5

按鍵,重複元素

按鍵,重複元素,
最大載入因子 5

成功查詢
scattered%20successful%20looukp.xlsx.practice
scattered%20successful%20looukp.xlsx.practice non unique
scattered%20successful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

不成功查詢
scattered%20unsuccessful%20looukp.xlsx.practice
scattered%20unsuccessful%20looukp.xlsx.practice non unique
scattered%20unsuccessful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

Visual Studio 2022 + Dinkumware, x64

插入
running%20insertion.xlsx.practice
running%20insertion.xlsx.practice non unique
running%20insertion.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

running%20insertion.xlsx.practice norehash
running%20insertion.xlsx.practice norehash non unique
running%20insertion.xlsx.practice norehash non unique 5

非重複元素,
先前 reserve

重複元素,
先前 reserve

重複元素,
最大載入因子 5,
先前 reserve

刪除
scattered%20erasure.xlsx.practice
scattered%20erasure.xlsx.practice non unique
scattered%20erasure.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

scattered%20erasure%20by%20key.xlsx.practice non unique
scattered%20erasure%20by%20key.xlsx.practice non unique 5

按鍵,重複元素

按鍵,重複元素,
最大載入因子 5

成功查詢
scattered%20successful%20looukp.xlsx.practice
scattered%20successful%20looukp.xlsx.practice non unique
scattered%20successful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

不成功查詢
scattered%20unsuccessful%20looukp.xlsx.practice
scattered%20unsuccessful%20looukp.xlsx.practice non unique
scattered%20unsuccessful%20looukp.xlsx.practice non unique 5

非重複元素

重複元素

重複元素,
最大載入因子 5

boost::unordered_(flat|node)_map

所有基準測試都是使用以下項目建立的:

  • absl::flat_hash_map<uint64_t, uint64_t>

  • boost::unordered_map<uint64_t, uint64_t>

  • boost::unordered_flat_map<uint64_t, uint64_t>

  • boost::unordered_node_map<uint64_t, uint64_t>

原始碼可以在這裡找到

插入基準測試會插入 n 個隨機值,其中 n 介於 10,000 到 1000 萬之間。

刪除基準測試會遍歷 n 個元素並刪除具有奇數鍵的元素(平均 50%)。

成功的查詢基準測試是透過以其原始插入順序查詢所有 n 個值來完成的。

不成功的查詢基準測試會使用 n 個隨機產生的整數,但使用不同的種子值。

GCC 12, x64

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

Clang 15, x64

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

Visual Studio 2022, x64

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

Clang 12, ARM64

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

GCC 12, x86

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

Clang 15, x86

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

Visual Studio 2022, x86

Running%20insertion.xlsx.plot
Running%20erasure.xlsx.plot
Scattered%20successful%20looukp.xlsx.plot
Scattered%20unsuccessful%20looukp.xlsx.plot

執行插入

執行刪除

成功查詢

不成功查詢

boost::concurrent_(flat|node)_map

所有基準測試都是使用以下項目建立的:

原始碼可以在這裡找到

基準測試會練習許多執行緒 T(介於 1 到 16 之間),同時執行隨機選擇的操作,這些操作包括更新成功查詢不成功查詢。操作中使用的鍵遵循具有不同偏斜參數的齊夫分佈:偏斜度越高,鍵在涵蓋範圍的較低值中越集中。

boost::concurrent_flat_mapboost::concurrent_node_map 會同時使用常規和批量訪問進行練習:在後一種情況下,查詢鍵會緩衝到本機陣列中,然後每次緩衝區達到 bulk_visit_size 時一併處理。

GCC 12, x64

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

Clang 15, x64

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

Visual Studio 2022, x64

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

Clang 12, ARM64

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

GCC 12, x86

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

Clang 15, x86

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

Visual Studio 2022, x86

Parallel%20workload.xlsx.500k%2C%200.01
Parallel%20workload.xlsx.500k%2C%200.5
Parallel%20workload.xlsx.500k%2C%200.99

50 萬次更新,450 萬次查詢
偏斜度=0.01

50 萬次更新,450 萬次查詢
偏斜度=0.5

50 萬次更新,450 萬次查詢
偏斜度=0.99

Parallel%20workload.xlsx.5M%2C%200.01
Parallel%20workload.xlsx.5M%2C%200.5
Parallel%20workload.xlsx.5M%2C%200.99

500 萬次更新,4500 萬次查詢
偏斜度=0.01

500 萬次更新,4500 萬次查詢
偏斜度=0.5

500 萬次更新,4500 萬次查詢
偏斜度=0.99

實作原理

封閉定址容器

boost::unordered_[multi]setboost::unordered_[multi]map 遵循無序關聯容器的標準要求,因此介面已固定。但是,仍然有一些實作決策要做。優先事項是符合標準和可移植性。

關於雜湊表的 Wikipedia 文章對雜湊表的實作問題進行了很好的總結。

資料結構

透過指定用於存取容器儲存桶的介面,該標準幾乎要求雜湊表使用封閉定址。

可以想像編寫使用另一種方法的雜湊表。例如,它可以使用開放定址,並使用查詢鏈來充當儲存桶,但這會有一些嚴重的問題

  • 標準要求指向元素的指標不能失效,因此元素不能儲存在單一陣列中,而是需要額外一層間接層——這會損失效率和大部分的記憶體優勢,而這些正是開放定址法的主要優點。

  • 本機迭代器效率會非常低,並且可能無法滿足複雜度要求。

  • 對於迭代器何時失效也有一些限制。由於開放定址法在高碰撞次數時效能會嚴重下降,這些限制可能會阻止在真正需要時進行重新雜湊。最大負載因子可以設定為相當低的值來解決這個問題——但標準要求它最初設定為 1.0。

  • 而且由於標準是以封閉定址法為考量所撰寫的,如果效能沒有反映出這一點,使用者會感到驚訝。

因此,使用封閉定址法。

桶子數量

在雜湊表中,有兩種常見的方法來選擇儲存桶的數量。一種是使用質數數量的儲存桶,另一種是使用 2 的冪次方。

使用質數數量的儲存桶,並使用雜湊函數結果的模數來選擇儲存桶,通常會得到不錯的結果。缺點是所需的模數運算相當耗費資源。這在大多數情況下是容器過去的做法。

使用 2 的冪次方可以更快地選擇要使用的儲存桶,但代價是會損失雜湊值的較高位元。對於某些特殊設計的雜湊函數,可以這樣做並仍然獲得良好的結果,但由於容器可以接受任意雜湊函數,因此不能依賴這一點。

為了避免這種情況,可以對雜湊函數應用轉換,例如,請參閱 Thomas Wang 關於整數雜湊函數的文章。不幸的是,像 Wang 這樣的轉換需要知道雜湊值中的位元數,因此僅在 size_t 為 64 位時才使用。

自 1.79.0 版本以來,改用費氏雜湊。在此實作中,儲存桶編號是透過使用 (h * m) >> (w - k) 來決定的,其中 h 是雜湊值,m2^w 除以黃金比例,w 是字組大小(32 或 64),而 2^k 是儲存桶的數量。這在速度和分配之間提供了良好的折衷。

自 1.80.0 版本以來,選擇質數作為儲存桶的數量,並搭配複雜的模數運算。這消除了像 1.79.0 版本那樣「混合」使用者雜湊函數結果的需求。

開放定址容器

C++ 無序關聯容器的標準規範對允許的實作施加了嚴格的限制,最重要的是隱含地假設了封閉定址法。稍微放寬此規範,便開啟了提供充分利用開放定址技術的容器變體的可能性。

boost::unordered_flat_set/unordered_node_setboost::unordered_flat_map/unordered_node_map 的設計遵循了 Peter Dimov 的 Boost.Unordered 的開發計畫。我們在此討論最相關的原則。

雜湊函數

鑑於其豐富的功能和跨平台互通性,boost::hash 仍然是開放定址容器的預設雜湊函數。碰巧的是,boost::hash 對於整數和其他基本類型不具備開放定址所需的統計屬性;為了處理這個問題,我們實作了後混合階段

     ah mulx C,
     hhigh(a) xor low(a),

其中 mulx擴展乘法(在 64 位元架構中為 128 位元,在 32 位元環境中為 64 位元),而 highlow 分別是擴展字的較高和較低一半。在 64 位元架構中,C 是 264φ 的整數部分,而在 32 位元中,C = 0xE817FB2Du 是從 Steele 和 Vigna (2021) 獲得的。

當直接使用適合開放定址的雜湊函數時,可以透過專用的 hash_is_avalanching 特性選擇退出後混合。字串類型的 boost::hash 特化被標記為雪崩。

平台互通性

只要它們的 std::size_t 大小相同,且使用者提供的雜湊函數和相等述詞也是可互通的,boost::unordered_flat_set/unordered_node_setboost::unordered_flat_map/unordered_node_map 的可觀察行為在不同的編譯器之間是決定性相同的 — 這包括對於相同操作序列,元素以完全相同的方式排序。

雖然實作在內部使用 SIMD 技術,例如 SSE2Neon(如果有的話),這不會影響互通性。例如,在具有 SSE2 的 x64 模式 Intel CPU 上的 Visual Studio 和在沒有任何支援 SIMD 技術的 IBM s390x 上的 GCC 的行為是相同的。

並行容器

Boost.Unordered 開放定址容器使用的相同資料結構也被選為 boost::concurrent_flat_set/boost::concurrent_node_setboost::concurrent_flat_map/boost::concurrent_node_map 的基礎。

  • 在非並行和並行場景中,開放定址比封閉定址替代方案更快。

  • 開放定址佈局非常適合使用最少的鎖定進行並行存取和修改。特別是,中繼資料陣列可用於實作查找,直到實際元素比較的最後一步都是無鎖定的。

  • 與 Boost.Unordered 平面容器的佈局相容性允許在並行容器及其非並行對應物之間快速傳輸所有元素,反之亦然。

雜湊函數和平台互通性

關於雜湊函數預設值平台互通性,並行容器會做出與 Boost.Unordered 開放定址容器相同的決策並提供相同的保證。

參考

類別模板 unordered_map

boost::unordered_map — 一個無序關聯容器,將唯一鍵與另一個值關聯。

概要

// #include <boost/unordered/unordered_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class unordered_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;
    using local_iterator       = implementation-defined;
    using const_local_iterator = implementation-defined;
    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    // construct/copy/destroy
    unordered_map();
    explicit unordered_map(size_type n,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l,
                    size_type n = implementation-defined,
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());
    unordered_map(const unordered_map& other);
    unordered_map(unordered_map&& other);
    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_map(const Allocator& a);
    unordered_map(const unordered_map& other, const Allocator& a);
    unordered_map(unordered_map&& other, const Allocator& a);
    unordered_map(std::initializer_list<value_type> il,
                  size_type n = implementation-defined
                  const hasher& hf = hasher(),
                  const key_equal& eql = key_equal(),
                  const allocator_type& a = allocator_type());
    unordered_map(size_type n, const allocator_type& a);
    unordered_map(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                    const allocator_type& a);
    unordered_map(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
    unordered_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                  const allocator_type& a);
    ~unordered_map();
    unordered_map& operator=(const unordered_map& other);
    unordered_map& operator=(unordered_map&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_move_assignable_v<Hash> &&
               boost::is_nothrow_move_assignable_v<Pred>);
    unordered_map& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    template<class P> std::pair<iterator, bool> insert(P&& obj);
    iterator       insert(const_iterator hint, const value_type& obj);
    iterator       insert(const_iterator hint, value_type&& obj);
    template<class P> iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);

    template<class... Args>
      std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      std::pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    node_type extract(const_iterator position);
    node_type extract(const key_type& k);
    template<class K> node_type extract(K&& k);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      quick_erase(const_iterator position);
    void      erase_return_void(const_iterator position);
    void      swap(unordered_map& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_swappable_v<Hash> &&
               boost::is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq);
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // element access
    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    template<class K> mapped_type& operator[](K&& k);
    mapped_type& at(const key_type& k);
    const mapped_type& at(const key_type& k) const;
    template<class K> mapped_type& at(const K& k);
    template<class K> const mapped_type& at(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    unordered_map(InputIterator, InputIterator, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, Pred,
                       Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    unordered_map(std::initializer_list<std::pair<Key, T>>,
                  typename see below::size_type = see below, Hash = Hash(),
                  Pred = Pred(), Allocator = Allocator())
      -> unordered_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                       boost::hash<iter-key-type<InputIterator>>,
                       std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, Allocator)
      -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                       boost::hash<iter-key-type<InputIterator>>,
                       std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
      -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                       std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                  Allocator)
      -> unordered_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_map(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> unordered_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type, Hash,
                  Allocator)
      -> unordered_map<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
              unordered_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_map<K, T, H, P, A>::size_type
       erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_map =
      boost::unordered_map<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

Key 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

T

T 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上實作等價關係。一個在 Key 類型的值上引起等價關係的二元函數物件。它接受兩個 Key 類型的引數,並傳回一個布林類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。

可以透過呼叫 insert 自動增加儲存桶的數量,或作為呼叫 rehash 的結果。

組態巨集

BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0

全域定義此巨集,以支援載入使用 Boost 1.84 之前的 Boost 版本儲存到 Boost.Serialization 封存中的 unordered_map

型別定義

typedef implementation-defined iterator;

值類型為 value_type 的迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined local_iterator;

具有與迭代器相同的值類型、差分類型以及指標和參考類型的迭代器。

local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined const_local_iterator;

具有與 const_iterator 相同的值類型、差分類型以及指標和參考類型的常數迭代器。

const_local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined node_type;

一個用於保存提取的容器元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class Iterator, class NodeType>
struct insert_return_type // name is exposition only
{
  Iterator position;
  bool     inserted;
  NodeType node;
};

其中 Iterator = iteratorNodeType = node_type


建構子

預設建構函式
unordered_map();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞、allocator_type() 作為分配器,以及最大負載因子為 1.0,建構一個空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_map(size_type n,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_map(InputIterator f, InputIterator l,
                size_type n = implementation-defined,
                const hasher& hf = hasher(),
                const key_equal& eql = key_equal(),
                const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_map(unordered_map const& other);

複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_map(unordered_map&& other);

移動建構函式。

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動建構的。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_map(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0 建構一個空容器,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_map(Allocator const& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_map(unordered_map const& other, Allocator const& a);

建構一個容器,複製 other 容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a


具備配置器的移動建構子
unordered_map(unordered_map&& other, Allocator const& a);

建構一個容器,移動 other 容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動插入 (move insertable) 的。


初始化列表建構子
unordered_map(std::initializer_list<value_type> il,
              size_type n = implementation-defined
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,eql 作為鍵值相等述詞,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_map(size_type n, allocator_type const& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設雜湊函數和鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_map(size_type n, hasher const& hf, allocator_type const& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                    const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,預設鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, const allocator_type& a);

建構一個空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
              const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_map();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_map& operator=(unordered_map const& other);

賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。

如果 Alloc::propagate_on_container_copy_assignment 存在且 Alloc::propagate_on_container_copy_assignment::valuetrue,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。

需求

value_type 是可複製建構的


移動賦值
unordered_map& operator=(unordered_map&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_move_assignable_v<Hash> &&
           boost::is_nothrow_move_assignable_v<Pred>);

移動賦值運算子。

如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。

需求

value_type 是可移動建構 (move constructible) 的。


初始化列表賦值
unordered_map& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中且可複製賦值 (CopyAssignable) 的。

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。


end
iterator end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

如果 args…​ 的形式為 k,v,則它會延遲建構整個物件,直到確定應該插入元素時,僅使用 k 引數進行檢查。當 map 的 key_type 是可移動建構的,或者當 k 引數是 key_type 時,會發生此最佳化。


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

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

position 是一個關於元素應該插入位置的建議。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

如果 args…​ 的形式為 k,v,則它會延遲建構整個物件,直到確定應該插入元素時,僅使用 k 引數進行檢查。當 map 的 key_type 是可移動建構的,或者當 k 引數是 key_type 時,會發生此最佳化。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


原地插入
template<class P> std::pair<iterator, bool> insert(P&& obj);

透過執行 emplace(std::forward<P>(value)) 將元素插入到容器中。

只有在 std::is_constructible<value_type, P&&>::valuetrue 時,才會參與多載解析。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的原地插入
template<class P> iterator insert(const_iterator hint, P&& obj);

透過執行 emplace_hint(hint, std::forward<P>(value)) 將元素插入到容器中。

只有在 std::is_constructible<value_type, P&&>::valuetrue 時,才會參與多載解析。

hint 是一個關於元素應該插入位置的建議。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可使用 *first 進行 原地建構 (EmplaceConstructible)X

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


try_emplace
template<class... Args>
  std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class K, class... Args>
  std::pair<iterator, bool> try_emplace(K&& k, Args&&... args)

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函數與 emplace 類似,差別在於 value_type 是使用以下方式建構的:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

而不是 emplace,後者只是將所有引數轉發到 value_type 的建構子。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 try_emplace
template<class... Args>
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args>
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
template<class K, class... Args>
  iterator try_emplace(const_iterator hint, K&& k, Args&&... args);

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

hint 是一個關於元素應該插入位置的建議。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函數與 emplace_hint 類似,差別在於 value_type 是使用以下方式建構的:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

而不是 emplace_hint,後者只是將所有引數轉發到 value_type 的建構子。

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


insert_or_assign
template<class M>
  std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class K, class M>
  std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))
傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 insert_or_assign
template<class M>
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M>
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

hint 是一個關於元素應該插入位置的建議。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


透過迭代器提取
node_type extract(const_iterator position);

移除 position 指向的元素。

傳回

擁有元素的 node_type

注意

使用此方法提取的節點可以插入到相容的 unordered_multimap 中。


透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

移除具有相當於 k 的鍵值的元素。

傳回

如果找到則傳回擁有元素的 node_type,否則傳回空的 node_type

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

使用此方法提取的節點可以插入到相容的 unordered_multimap 中。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


使用 node_handle 插入
insert_return_type insert(node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh 所擁有的元素。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則回傳一個 insert_return_type,其中:inserted 等於 falseposition 等於 end(),且 node 為空。

否則,如果已經存在一個具有等價鍵的元素,則回傳一個 insert_return_type,其中:inserted 等於 falseposition 指向一個匹配的元素,且 node 包含來自 nh 的節點。

否則,如果插入成功,則回傳一個 insert_return_type,其中:inserted 等於 trueposition 指向新插入的元素,且 node 為空。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用於插入從相容的 unordered_multimap 中提取的節點。


使用提示和 node_handle 插入
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh 所擁有的元素。

如果容器中已存在具有等價鍵的元素,則對 nh 沒有影響(即 nh 仍然包含該節點)。

hint 是一個關於元素應該插入位置的建議。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則回傳 end()

如果容器中已存在具有等價鍵的元素,則回傳一個指向該元素的迭代器。

否則,回傳一個指向新插入元素的迭代器。

拋出

如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用於插入從相容的 unordered_multimap 中提取的節點。


依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

刪除前,position 後面的迭代器。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。


快速刪除 (quick_erase)
void quick_erase(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


erase_return_void
void erase_return_void(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


交換 (swap)
void swap(unordered_map& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_swappable_v<Hash> &&
           boost::is_nothrow_swappable_v<Pred>);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


清除 (clear)
void clear();

刪除容器中的所有元素。

後置條件

size() == 0

拋出

永遠不會擲出例外。


合併 (merge)
template<class H2, class P2>
  void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
template<class H2, class P2>
  void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);

嘗試透過迭代 source 並提取 source 中未包含在 *this 中的任何節點,然後將其插入 *this 中來「合併」兩個容器。

因為 source 可以具有不同的雜湊函數和鍵相等述詞,所以 source 中每個節點的鍵都會使用 this->hash_function() 重新雜湊,然後,如果需要,則使用 this->key_eq() 比較。

如果 this->get_allocator() != source.get_allocator(),則此函數的行為未定義。

此函數不會複製或移動任何元素,而是單純將節點從 source 重新定位到 *this 中。

注意
  • 指向和引用已傳輸元素的指標和參考保持有效。

  • 使指向已傳輸元素的迭代器失效。

  • 使屬於 *this 的迭代器失效。

  • 指向 source 中未傳輸元素的迭代器保持有效。


觀察器

get_allocator
allocator_type get_allocator() const;

hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
template<class K>
  const_iterator find(const K& k) const;
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq);
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq) const;
傳回

指向具有與 k 等價鍵的元素的迭代器,如果不存在此類元素,則為 b.end()

注意

包含 CompatibleKeyCompatibleHashCompatiblePredicate 的樣板多載是非標準擴充功能,可讓您使用相容的雜湊函數和相等述詞,來處理不同類型的鍵,以避免昂貴的類型轉換。一般來說,不鼓勵使用它,而應使用 K 成員函數樣板。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用

如果容器尚未包含具有與 k 等價鍵的元素,則插入值 std::pair<key_type const, mapped_type>(k, mapped_type())

傳回

x.second 的參考,其中 x 是容器中已存在的元素,或是具有與 k 等價鍵的新插入元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


at
mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
template<class K> mapped_type& at(const K& k);
template<class K> const mapped_type& at(const K& k) const;
傳回

x.second 的參考,其中 x 是(唯一)鍵與 k 等價的元素。

拋出

如果不存在此類元素,則擲出類型為 std::out_of_range 的例外物件。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

桶子的數量。


max_bucket_count
size_type max_bucket_count() const noexcept;
傳回

桶子數量的上限。


bucket_size
size_type bucket_size(size_type n) const;
需求

n < bucket_count()

傳回

桶子 n 中的元素數量。


儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回

將包含鍵為 k 的元素的儲存桶的索引。

後置條件

回傳值小於 bucket_count()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的本機迭代器。


end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的本機迭代器。


cbegin
const_local_iterator cbegin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的常數本機迭代器。


cend
const_local_iterator cend(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的常數本機迭代器。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

每個儲存桶的平均元素數量。


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

回傳目前的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

變更容器的最大負載因子,使用 z 作為提示。


重新雜湊 (rehash)
void rehash(size_type n);

變更儲存桶數量,使其至少有 n 個儲存桶,且載入因子小於或等於最大載入因子。在適用的情況下,這會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor())),或者如果 n > 0a.max_load_factor() == std::numeric_limits<float>::infinity(),則等同於 a.rehash(1)

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。

推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。

交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
            unordered_map<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_map<K, T, H, P, A>::size_type
    erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

可以使用此程式庫提供的 API,透過 Boost.Serialization 封存/擷取 unordered_map。支援規則和 XML 封存。

將 unordered_map 儲存到封存檔

unordered_map x 的所有元素儲存到封存檔 (XML 封存) ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。


從封存檔載入 unordered_map

刪除 unordered_map x 的所有現有元素,並從封存檔 (XML 封存) ar 插入儲存在 ar 讀取之儲存區的原始 unordered_map other 元素的還原副本。

需求

value_type 可透過 (std::remove_const<key_type>::type&&, std::remove_const<mapped_type>::type&&) 進行就地建構 (EmplaceConstructible)x.key_equal() 的功能與 other.key_equal() 等效。

注意

如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0,此操作才能成功;否則會擲回例外。


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_map x 之前已儲存到 ar,並且在儲存 x 和儲存 it 之間,未對 x 執行任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_map,則在載入 x 和載入 it 之間,未對 x 執行任何修改操作。

類別模板 unordered_multimap

boost::unordered_multimap — 一個無序的關聯容器,將鍵與另一個值相關聯。可以多次儲存相同的鍵。

概要

// #include <boost/unordered/unordered_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class unordered_multimap {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;
    using local_iterator       = implementation-defined;
    using const_local_iterator = implementation-defined;
    using node_type            = implementation-defined;

    // construct/copy/destroy
    unordered_multimap();
    explicit unordered_multimap(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_multimap(const unordered_multimap& other);
    unordered_multimap(unordered_multimap&& other);
    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_multimap(const Allocator& a);
    unordered_multimap(const unordered_multimap& other, const Allocator& a);
    unordered_multimap(unordered_multimap&& other, const Allocator& a);
    unordered_multimap(std::initializer_list<value_type> il,
                       size_type n = implementation-defined,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_multimap(size_type n, const allocator_type& a);
    unordered_multimap(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_multimap(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_multimap(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a);
    unordered_multimap(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_multimap();
    unordered_multimap& operator=(const unordered_multimap& other);
    unordered_multimap& operator=(unordered_multimap&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_move_assignable_v<Hash> &&
               boost::is_nothrow_move_assignable_v<Pred>);
    unordered_multimap& operator=(std::initializer_list<value_type> il);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    template<class P> iterator insert(P&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class P> iterator insert(const_iterator hint, P&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type> il);

    node_type extract(const_iterator position);
    node_type extract(const key_type& k);
    template<class K> node_type extract(K&& k);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      quick_erase(const_iterator position);
    void      erase_return_void(const_iterator position);
    void      swap(unordered_multimap& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_swappable_v<Hash> &&
               boost::is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq);
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            Pred, Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    unordered_multimap(std::initializer_list<std::pair<Key, T>>,
                       typename see below::size_type = see below, Hash = Hash(),
                       Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, Allocator)
      -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_multimap(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Allocator)
      -> unordered_multimap<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_multimap(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> unordered_multimap<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_multimap(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Hash, Allocator)
      -> unordered_multimap<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
              unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_multimap<K, T, H, P, A>::size_type
      erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_multimap =
      boost::unordered_multimap<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

Key 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

T

T 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上實作等價關係。一個在 Key 類型的值上引起等價關係的二元函數物件。它接受兩個 Key 類型的引數,並傳回一個布林類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。

可以透過呼叫 insert 自動增加儲存桶的數量,或作為呼叫 rehash 的結果。

組態巨集

BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0

全域定義此巨集,以支援載入使用 Boost 1.84 之前版本的 Boost.Serialization 封存檔儲存的 unordered_multimap

型別定義

typedef implementation-defined iterator;

值類型為 value_type 的迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined local_iterator;

具有與迭代器相同的值類型、差分類型以及指標和參考類型的迭代器。

local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined const_local_iterator;

具有與 const_iterator 相同的值類型、差分類型以及指標和參考類型的常數迭代器。

const_local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined node_type;

詳情請參閱 node_handle_map。


建構子

預設建構函式
unordered_multimap();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞、allocator_type() 作為分配器,以及最大負載因子為 1.0,建構一個空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_multimap(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
unordered_multimap(InputIterator f, InputIterator l,
                   size_type n = implementation-defined,
                   const hasher& hf = hasher(),
                   const key_equal& eql = key_equal(),
                   const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_multimap(const unordered_multimap& other);

複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_multimap(unordered_multimap&& other);

移動建構函式。

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動建構的。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0 建構一個空容器,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_multimap(const Allocator& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_multimap(const unordered_multimap& other, const Allocator& a);

建構一個容器,複製 other 容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a


具備配置器的移動建構子
unordered_multimap(unordered_multimap&& other, const Allocator& a);

建構一個容器,移動 other 容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動插入 (move insertable) 的。


初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il,
                   size_type n = implementation-defined,
                   const hasher& hf = hasher(),
                   const key_equal& eql = key_equal(),
                   const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,eql 作為鍵值相等述詞,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_multimap(size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設雜湊函數和鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_multimap(size_type n, const hasher& hf, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
template<class InputIterator>
  unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                     const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,預設鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, const allocator_type& a);

建構一個空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                   const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_multimap();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_multimap& operator=(const unordered_multimap& other);

賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。

如果 Alloc::propagate_on_container_copy_assignment 存在且 Alloc::propagate_on_container_copy_assignment::valuetrue,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。

需求

value_type 是可複製建構的


移動賦值
unordered_multimap& operator=(unordered_multimap&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_move_assignable_v<Hash> &&
           boost::is_nothrow_move_assignable_v<Pred>);

移動賦值運算子。

如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。

需求

value_type 是可移動建構 (move constructible) 的。


初始化列表賦值
unordered_multimap& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中且可複製賦值 (CopyAssignable) 的。

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。


end
iterator       end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> iterator emplace(Args&&... args);

在容器中插入一個使用引數 args 建構的物件。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


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

在容器中插入一個使用引數 args 建構的物件。

position 是一個關於元素應該插入位置的建議。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


複製插入
iterator insert(const value_type& obj);

在容器中插入 obj

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


移動插入
iterator insert(value_type&& obj);

在容器中插入 obj

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


原地插入
template<class P> iterator insert(P&& obj);

透過執行 emplace(std::forward<P>(value)) 將元素插入到容器中。

只有在 std::is_constructible<value_type, P&&>::valuetrue 時,才會參與多載解析。

傳回

指向插入元素的迭代器。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

在容器中插入 obj

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

在容器中插入 obj

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的原地插入
template<class P> iterator insert(const_iterator hint, P&& obj);

透過執行 emplace_hint(hint, std::forward<P>(value)) 將元素插入到容器中。

只有在 std::is_constructible<value_type, P&&>::valuetrue 時,才會參與多載解析。

hint 是一個關於元素應該插入位置的建議。

傳回

指向插入元素的迭代器。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入容器中。

需求

value_type 可使用 *first 進行 原地建構 (EmplaceConstructible)X

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入初始化列表
void insert(std::initializer_list<value_type> il);

將一系列元素插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


透過迭代器提取
node_type extract(const_iterator position);

移除 position 指向的元素。

傳回

擁有元素的 node_type

注意

使用此方法提取的節點可以插入到相容的 unordered_map 中。


透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

移除具有相當於 k 的鍵值的元素。

傳回

如果找到則傳回擁有元素的 node_type,否則傳回空的 node_type

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

使用此方法提取的節點可以插入到相容的 unordered_map 中。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


使用 node_handle 插入
iterator insert(node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則插入 nh 所擁有的元素。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則返回 end()

否則,回傳一個指向新插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用來插入從相容的 unordered_map 中提取的節點。


使用提示和 node_handle 插入
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則插入 nh 所擁有的元素。

hint 是一個關於元素應該插入位置的建議。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則返回 end()

否則,回傳一個指向新插入元素的迭代器。

拋出

如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用來插入從相容的 unordered_map 中提取的節點。


依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

刪除前,position 後面的迭代器。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。


快速刪除 (quick_erase)
void quick_erase(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


erase_return_void
void erase_return_void(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


交換 (swap)
void swap(unordered_multimap& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_swappable_v<Hash> &&
           boost::is_nothrow_swappable_v<Pred>);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0

拋出

永遠不會擲出例外。


合併 (merge)
template<class H2, class P2>
  void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);
template<class H2, class P2>
  void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);

嘗試透過迭代 source 並提取 source 中的所有節點並將其插入到 *this 中來「合併」兩個容器。

因為 source 可以具有不同的雜湊函數和鍵相等述詞,所以 source 中每個節點的鍵都會使用 this->hash_function() 重新雜湊,然後,如果需要,則使用 this->key_eq() 比較。

如果 this->get_allocator() != source.get_allocator(),則此函數的行為未定義。

此函數不會複製或移動任何元素,而是單純將節點從 source 重新定位到 *this 中。

注意
  • 指向和引用已傳輸元素的指標和參考保持有效。

  • 使指向已傳輸元素的迭代器失效。

  • 使屬於 *this 的迭代器失效。

  • 指向 source 中未傳輸元素的迭代器保持有效。


觀察器

get_allocator
allocator_type get_allocator() const;

hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
template<class K>
  const_iterator find(const K& k) const;
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq);
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq) const;
傳回

指向具有與 k 等價鍵的元素的迭代器,如果不存在此類元素,則為 b.end()

注意

包含 CompatibleKeyCompatibleHashCompatiblePredicate 的樣板多載是非標準擴充功能,可讓您使用相容的雜湊函數和相等述詞,來處理不同類型的鍵,以避免昂貴的類型轉換。一般來說,不鼓勵使用它,而應使用 K 成員函數樣板。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

桶子的數量。


max_bucket_count
size_type max_bucket_count() const noexcept;
傳回

桶子數量的上限。


bucket_size
size_type bucket_size(size_type n) const;
需求

n < bucket_count()

傳回

桶子 n 中的元素數量。


儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回

將包含鍵為 k 的元素的儲存桶的索引。

後置條件

回傳值小於 bucket_count()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的本機迭代器。


end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的本機迭代器。


cbegin
const_local_iterator cbegin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的常數本機迭代器。


cend
const_local_iterator cend(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的常數本機迭代器。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

每個儲存桶的平均元素數量。


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

回傳目前的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

變更容器的最大負載因子,使用 z 作為提示。


重新雜湊 (rehash)
void rehash(size_type n);

變更儲存桶數量,使其至少有 n 個儲存桶,且載入因子小於或等於最大載入因子。在適用的情況下,這會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor())),或者如果 n > 0a.max_load_factor() == std::numeric_limits<float>::infinity(),則等同於 a.rehash(1)

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_multimap<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size()x 中的每個等效鍵群組在 y 中都有相同鍵的群組,並且該群組是一個排列 (使用 operator== 來比較值類型),則返回 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_multimap<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size()x 中的每個等效鍵群組在 y 中都有相同鍵的群組,並且該群組是一個排列 (使用 operator== 來比較值類型),則返回 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
            unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_multimap<K, T, H, P, A>::size_type
    erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

unordered_multimap 可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。

將 unordered_multimap 儲存到封存檔

unordered_multimap x 的所有元素儲存到封存檔 (XML 封存檔) ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。


從封存檔載入 unordered_multimap

刪除 unordered_multimap x 的所有先前存在的元素,並從封存檔 (XML 封存檔) ar 插入還原的原始 unordered_multimap other 的元素副本,這些副本儲存在 ar 讀取的儲存空間中。

需求

value_type 可透過 (std::remove_const<key_type>::type&&, std::remove_const<mapped_type>::type&&) 進行就地建構 (EmplaceConstructible)x.key_equal() 的功能與 other.key_equal() 等效。

注意

如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0,此操作才能成功;否則會擲回例外。


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_multimap x 之前已儲存到 ar,並且在儲存 x 和儲存 it 之間,未對 x 執行任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_multimap,則在載入 x 和載入 it 之間,未對 x 執行任何修改操作。

類別模板 unordered_set

boost::unordered_set — 一個無序的關聯容器,用於儲存唯一值。

概要

// #include <boost/unordered/unordered_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class unordered_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;
    using local_iterator       = implementation-defined;
    using const_local_iterator = implementation-defined;
    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    // construct/copy/destroy
    unordered_set();
    explicit unordered_set(size_type n,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l,
                    size_type n = implementation-defined,
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());
    unordered_set(const unordered_set& other);
    unordered_set(unordered_set&& other);
    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_set(const Allocator& a);
    unordered_set(const unordered_set& other, const Allocator& a);
    unordered_set(unordered_set&& other, const Allocator& a);
    unordered_set(std::initializer_list<value_type> il,
                  size_type n = implementation-defined,
                  const hasher& hf = hasher(),
                  const key_equal& eql = key_equal(),
                  const allocator_type& a = allocator_type());
    unordered_set(size_type n, const allocator_type& a);
    unordered_set(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                    const allocator_type& a);
    unordered_set(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
    unordered_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                  const allocator_type& a);
    ~unordered_set();
    unordered_set& operator=(const unordered_set& other);
    unordered_set& operator=(unordered_set&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_move_assignable_v<Hash> &&
               boost::is_nothrow_move_assignable_v<Pred>);
    unordered_set& operator=(std::initializer_list<value_type> il);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    template<class K> std::pair<iterator, bool> insert(K&& k);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class K> iterator insert(const_iterator hint, K&& k);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& k);
    template<class K> node_type extract(K&& k);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      quick_erase(const_iterator position);
    void      erase_return_void(const_iterator position);
    void      swap(unordered_set& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_swappable_v<Hash> &&
               boost::is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq);
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                          CompatiblePredicate const& eq) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    unordered_set(InputIterator, InputIterator, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    unordered_set(std::initializer_list<T>, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_set<iter-value-type<InputIterator>,
                       boost::hash<iter-value-type<InputIterator>>,
                       std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_set(InputIterator, InputIterator, Allocator)
      -> unordered_set<iter-value-type<InputIterator>,
                       boost::hash<iter-value-type<InputIterator>>,
                       std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_set(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
      -> unordered_set<iter-value-type<InputIterator>, Hash,
                       std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    unordered_set(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    unordered_set(std::initializer_list<T>, Allocator)
      -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_set(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_set<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& x,
                    const unordered_set<Key, Hash, Pred, Alloc>& y);

  template<class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_set<Key, Hash, Pred, Alloc>& x,
                    const unordered_set<Key, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_set<Key, Hash, Pred, Alloc>& x,
              unordered_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class H, class P, class A, class Predicate>
    typename unordered_set<K, H, P, A>::size_type
      erase_if(unordered_set<K, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_set =
      boost::unordered_set<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上實作等價關係。一個在 Key 類型的值上引起等價關係的二元函數物件。它接受兩個 Key 類型的引數,並傳回一個布林類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。

可以透過呼叫 insert 自動增加儲存桶的數量,或作為呼叫 rehash 的結果。

組態巨集

BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0

全域定義此巨集,以支援載入使用 Boost 1.84 之前版本的 Boost.Serialization 封存檔儲存的 unordered_set

型別定義

typedef implementation-defined iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined local_iterator;

具有與迭代器相同的值類型、差分類型以及指標和參考類型的迭代器。

local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined const_local_iterator;

具有與 const_iterator 相同的值類型、差分類型以及指標和參考類型的常數迭代器。

const_local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined node_type;

一個用於保存提取的容器元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class Iterator, class NodeType>
struct insert_return_type // name is exposition only
{
  Iterator position;
  bool     inserted;
  NodeType node;
};

其中 Iterator = iteratorNodeType = node_type


建構子

預設建構函式
unordered_set();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞、allocator_type() 作為分配器,以及最大負載因子為 1.0,建構一個空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_set(size_type n,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_set(InputIterator f, InputIterator l,
                size_type n = implementation-defined,
                const hasher& hf = hasher(),
                const key_equal& eql = key_equal(),
                const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_set(const unordered_set& other);

複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_set(unordered_set&& other);

移動建構函式。

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動建構的。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_set(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0 建構一個空容器,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_set(const Allocator& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_set(const unordered_set& other, const Allocator& a);

建構一個容器,複製 other 容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a


具備配置器的移動建構子
unordered_set(unordered_set&& other, const Allocator& a);

建構一個容器,移動 other 容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動插入 (move insertable) 的。


初始化列表建構子
unordered_set(std::initializer_list<value_type> il,
              size_type n = implementation-defined,
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,eql 作為鍵值相等述詞,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_set(size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設雜湊函數和鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_set(size_type n, const hasher& hf, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
template<class InputIterator>
  unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,預設鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, const allocator_type& a);

建構一個空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
              const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_set();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_set& operator=(const unordered_set& other);

賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。

如果 Alloc::propagate_on_container_copy_assignment 存在且 Alloc::propagate_on_container_copy_assignment::valuetrue,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。

需求

value_type 是可複製建構的


移動賦值
unordered_set& operator=(unordered_set&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_move_assignable_v<Hash> &&
           boost::is_nothrow_move_assignable_v<Pred>);

移動賦值運算子。

如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。

需求

value_type 是可移動建構 (move constructible) 的。


初始化列表賦值
unordered_set& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中且可複製賦值 (CopyAssignable) 的。


迭代器

begin
iterator       begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。


end
iterator       end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有等效值的元素,則在容器中插入一個使用引數 args 建構的物件。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果執行了插入操作,則迭代器指向新插入的元素。否則,它指向具有等效值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


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

如果容器中沒有具有等效值的元素,則在容器中插入一個使用引數 args 建構的物件。

position 是一個關於元素應該插入位置的建議。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具有提示的透明插入
template<class K> iterator insert(const_iterator hint, K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可使用 *first 進行 原地建構 (EmplaceConstructible)X

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


透過迭代器提取
node_type extract(const_iterator position);

移除 position 指向的元素。

傳回

擁有元素的 node_type

注意

在 C++17 中,使用此方法提取的節點可以插入到相容的 unordered_multiset 中,但目前尚不支援。


按值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

移除具有相當於 k 的鍵值的元素。

傳回

如果找到則傳回擁有元素的 node_type,否則傳回空的 node_type

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

在 C++17 中,使用此方法提取的節點可以插入到相容的 unordered_multiset 中,但目前尚不支援。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


使用 node_handle 插入
insert_return_type insert(node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh 所擁有的元素。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則回傳一個 insert_return_type,其中:inserted 等於 falseposition 等於 end(),且 node 為空。

否則,如果已經存在一個具有等價鍵的元素,則回傳一個 insert_return_type,其中:inserted 等於 falseposition 指向一個匹配的元素,且 node 包含來自 nh 的節點。

否則,如果插入成功,則回傳一個 insert_return_type,其中:inserted 等於 trueposition 指向新插入的元素,且 node 為空。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

在 C++17 中,這可以用來插入從相容的 unordered_multiset 中提取的節點,但目前尚不支援。


使用提示和 node_handle 插入
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh 所擁有的元素。

如果容器中已存在具有等價鍵的元素,則對 nh 沒有影響(即 nh 仍然包含該節點)。

hint 是一個關於元素應該插入位置的建議。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則回傳 end()

如果容器中已存在具有等價鍵的元素,則回傳一個指向該元素的迭代器。

否則,回傳一個指向新插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用來插入從相容的 unordered_multiset 中提取的節點。


依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

刪除前,position 後面的迭代器。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。


按值刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。


快速刪除 (quick_erase)
void quick_erase(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


erase_return_void
void erase_return_void(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


交換 (swap)
void swap(unordered_set& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_swappable_v<Hash> &&
           boost::is_nothrow_swappable_v<Pred>);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0

拋出

永遠不會擲出例外。


合併 (merge)
template<class H2, class P2>
  void merge(unordered_set<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_set<Key, H2, P2, Allocator>&& source);
template<class H2, class P2>
  void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);

嘗試透過迭代 source 並提取 source 中未包含在 *this 中的任何節點,然後將其插入 *this 中來「合併」兩個容器。

因為 source 可以具有不同的雜湊函數和鍵相等述詞,所以 source 中每個節點的鍵都會使用 this->hash_function() 重新雜湊,然後,如果需要,則使用 this->key_eq() 比較。

如果 this->get_allocator() != source.get_allocator(),則此函數的行為未定義。

此函數不會複製或移動任何元素,而是單純將節點從 source 重新定位到 *this 中。

注意
  • 指向和引用已傳輸元素的指標和參考保持有效。

  • 使指向已傳輸元素的迭代器失效。

  • 使屬於 *this 的迭代器失效。

  • 指向 source 中未傳輸元素的迭代器保持有效。


觀察器

get_allocator
allocator_type get_allocator() const;

hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
template<class K>
  const_iterator find(const K& k) const;
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  iterator       find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq);
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  const_iterator find(CompatibleKey const& k, CompatibleHash const& hash,
                      CompatiblePredicate const& eq) const;
傳回

指向具有與 k 等價鍵的元素的迭代器,如果不存在此類元素,則為 b.end()

注意

包含 CompatibleKeyCompatibleHashCompatiblePredicate 的樣板多載是非標準擴充功能,可讓您使用相容的雜湊函數和相等述詞,來處理不同類型的鍵,以避免昂貴的類型轉換。一般來說,不鼓勵使用它,而應使用 K 成員函數樣板。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

桶子的數量。


max_bucket_count
size_type max_bucket_count() const noexcept;
傳回

桶子數量的上限。


bucket_size
size_type bucket_size(size_type n) const;
需求

n < bucket_count()

傳回

桶子 n 中的元素數量。


儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回

將包含鍵為 k 的元素的儲存桶的索引。

後置條件

回傳值小於 bucket_count()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的本機迭代器。


end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的本機迭代器。


cbegin
const_local_iterator cbegin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的常數本機迭代器。


cend
const_local_iterator cend(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的常數本機迭代器。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

每個儲存桶的平均元素數量。


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

回傳目前的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

變更容器的最大負載因子,使用 z 作為提示。


重新雜湊 (rehash)
void rehash(size_type n);

變更儲存桶數量,使其至少有 n 個儲存桶,且載入因子小於或等於最大載入因子。在適用的情況下,這會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor())),或者如果 n > 0a.max_load_factor() == std::numeric_limits<float>::infinity(),則等同於 a.rehash(1)

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。

推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& x,
                  const unordered_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_set<Key, Hash, Pred, Alloc>& x,
                  const unordered_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


交換

template<class Key, class Hash, class Pred, class Alloc>
  void swap(unordered_set<Key, Hash, Pred, Alloc>& x,
            unordered_set<Key, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


erase_if

template<class K, class H, class P, class A, class Predicate>
  typename unordered_set<K, H, P, A>::size_type
    erase_if(unordered_set<K, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

unordered_set 可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。

將 unordered_set 儲存到封存檔

unordered_set x 的所有元素儲存到封存檔 (XML 封存檔) ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。


從封存檔載入 unordered_set

刪除 unordered_set x 的所有先前存在的元素,並從封存檔 (XML 封存檔) ar 插入還原的原始 unordered_set other 的元素副本,這些副本儲存在 ar 讀取的儲存空間中。

需求

value_type可移動插入 (MoveInsertable) 的。x.key_equal() 的功能與 other.key_equal() 等效。

注意

如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0,此操作才能成功;否則會擲回例外。


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_set x 之前已儲存到 ar,並且在儲存 x 和儲存 it 之間,未對 x 執行任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_set,則在載入 x 和載入 it 之間,未對 x 執行任何修改操作。

類別模板 unordered_multiset

boost::unordered_multiset — 一個無序的關聯容器,用於儲存值。可以多次儲存相同的鍵。

概要

// #include <boost/unordered/unordered_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class unordered_multiset {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;
    using local_iterator       = implementation-defined;
    using const_local_iterator = implementation-defined;
    using node_type            = implementation-defined;

    // construct/copy/destroy
    unordered_multiset();
    explicit unordered_multiset(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_multiset(const unordered_multiset& other);
    unordered_multiset(unordered_multiset&& other);
    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_multiset(const Allocator& a);
    unordered_multiset(const unordered_multiset& other, const Allocator& a);
    unordered_multiset(unordered_multiset&& other, const Allocator& a);
    unordered_multiset(std::initializer_list<value_type> il,
                       size_type n = implementation-defined,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_multiset(size_type n, const allocator_type& a);
    unordered_multiset(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_multiset(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_multiset(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a)
    unordered_multiset(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_multiset();
    unordered_multiset& operator=(const unordered_multiset& other);
    unordered_multiset& operator=(unordered_multiset&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_move_assignable_v<Hash> &&
               boost::is_nothrow_move_assignable_v<Pred>);
    unordered_multiset& operator=(std::initializer_list<value_type> il);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> iterator emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type> il);

    node_type extract(const_iterator position);
    node_type extract(const key_type& k);
    template<class K> node_type extract(K&& k);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    template<class K> size_type erase(K&& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      quick_erase(const_iterator position);
    void      erase_return_void(const_iterator position);
    void      swap(unordered_multiset&)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
               boost::is_nothrow_swappable_v<Hash> &&
               boost::is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      iterator       find(CompatibleKey const&, CompatibleHash const&,
                          CompatiblePredicate const&);
    template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
      const_iterator  find(CompatibleKey const&, CompatibleHash const&,
                           CompatiblePredicate const&) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    template<class K> size_type bucket(const K& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    unordered_multiset(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    unordered_multiset(std::initializer_list<T>, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_multiset<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multiset(InputIterator, InputIterator, Allocator)
      -> unordered_multiset<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_multiset<iter-value-type<InputIterator>, Hash,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    unordered_multiset(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    unordered_multiset(std::initializer_list<T>, Allocator)
      -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_multiset(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_multiset<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& x,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& y);

  template<class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multiset<Key, Hash, Pred, Alloc>& x,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x,
              unordered_multiset<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class H, class P, class A, class Predicate>
    typename unordered_multiset<K, H, P, A>::size_type
      erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_multiset =
      boost::unordered_multiset<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可從容器中擦除(即 allocator_traits 可以銷毀它)。

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上實作等價關係。一個在 Key 類型的值上引起等價關係的二元函數物件。它接受兩個 Key 類型的引數,並傳回一個布林類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

這些元素會組織到儲存桶中。具有相同雜湊碼的鍵會儲存在同一個儲存桶中,而具有等效鍵的元素會彼此相鄰儲存。

可以透過呼叫 insert 自動增加儲存桶的數量,或作為呼叫 rehash 的結果。

組態巨集

BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0

全域定義此巨集,以支援載入使用 Boost 1.84 之前版本的 Boost.Serialization 封存檔儲存的 unordered_multiset

型別定義

typedef implementation-defined iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined local_iterator;

具有與迭代器相同的值類型、差分類型以及指標和參考類型的迭代器。

local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined const_local_iterator;

具有與 const_iterator 相同的值類型、差分類型以及指標和參考類型的常數迭代器。

const_local_iterator 物件可以用於迭代單個儲存桶。


typedef implementation-defined node_type;

詳情請參閱 node_handle_set。


建構子

預設建構函式
unordered_multiset();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞、allocator_type() 作為分配器,以及最大負載因子為 1.0,建構一個空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_multiset(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_multiset(InputIterator f, InputIterator l,
                     size_type n = implementation-defined,
                     const hasher& hf = hasher(),
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞、a 作為分配器,以及最大負載因子為 1.0,建構一個至少具有 n 個儲存桶的空容器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_multiset(const unordered_multiset& other);

複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_multiset(unordered_multiset&& other);

移動建構函式。

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動建構的。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0 建構一個空容器,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_multiset(const Allocator& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_multiset(const unordered_multiset& other, const Allocator& a);

建構一個容器,複製 other 容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a


具備配置器的移動建構子
unordered_multiset(unordered_multiset&& other, const Allocator& a);

建構一個容器,移動 other 容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a

注意

這是使用 Boost.Move 實作的。

需求

value_type 是可移動插入 (move insertable) 的。


初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il,
                   size_type n = implementation-defined,
                   const hasher& hf = hasher(),
                   const key_equal& eql = key_equal(),
                   const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,eql 作為鍵值相等述詞,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_multiset(size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設雜湊函數和鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_multiset(size_type n, const hasher& hf, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,預設鍵值相等述詞,a 作為配置器,最大載入因子為 1.0

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
template<class InputIterator>
  unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                     const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,預設鍵值相等述詞,最大載入因子為 1.0,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il, const allocator_type& a);

建構一個空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il, size_type n, const allocator_type& a)

建構一個至少有 n 個儲存桶的空容器,使用 a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
    unordered_multiset(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);

建構一個至少有 n 個儲存桶的空容器,使用 hf 作為雜湊函數,a 作為配置器,最大載入因子為 1.0,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_multiset();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_multiset& operator=(const unordered_multiset& other);

賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。

如果 Alloc::propagate_on_container_copy_assignment 存在且 Alloc::propagate_on_container_copy_assignment::valuetrue,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。

需求

value_type 是可複製建構的


移動賦值
unordered_multiset& operator=(unordered_multiset&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_move_assignable_v<Hash> &&
           boost::is_nothrow_move_assignable_v<Pred>);

移動賦值運算子。

如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。

需求

value_type 是可移動建構 (move constructible) 的。


初始化列表賦值
unordered_multiset& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中且可複製賦值 (CopyAssignable) 的。


迭代器

begin
iterator       begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。


end
iterator       end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> iterator emplace(Args&&... args);

在容器中插入一個使用引數 args 建構的物件。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


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

在容器中插入一個使用引數 args 建構的物件。

hint 是一個關於元素應該插入位置的建議。

需求

value_type 可使用 args 進行 原地建構 (EmplaceConstructible)X

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


複製插入
iterator insert(const value_type& obj);

在容器中插入 obj

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


移動插入
iterator insert(value_type&& obj);

在容器中插入 obj

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

在容器中插入 obj

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

在容器中插入 obj

hint 是一個關於元素應該插入位置的建議。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

指向插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入容器中。

需求

value_type 可使用 *first 進行 原地建構 (EmplaceConstructible)X

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


插入初始化列表
void insert(std::initializer_list<value_type> il);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。


透過迭代器提取
node_type extract(const_iterator position);

移除 position 指向的元素。

傳回

擁有元素的 node_type

注意

使用此方法提取的節點可以插入到相容的 unordered_set 中。


按值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

移除具有相當於 k 的鍵值的元素。

傳回

如果找到則傳回擁有元素的 node_type,否則傳回空的 node_type

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

使用此方法提取的節點可以插入到相容的 unordered_set 中。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


使用 node_handle 插入
iterator insert(node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則插入 nh 所擁有的元素。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則返回 end()

否則,回傳一個指向新插入元素的迭代器。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用來插入從相容的 unordered_set 中提取的節點。


使用提示和 node_handle 插入
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 為空,則不會產生任何作用。

否則插入 nh 所擁有的元素。

hint 是一個關於元素應該插入位置的建議。

需求

nh 為空,或 nh.get_allocator() 等於容器的配置器。

傳回

如果 nh 為空,則返回 end()

否則,回傳一個指向新插入元素的迭代器。

拋出

如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。

注意

關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。

可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。

指向元素的指標和參考永遠不會失效。

這可以用來插入從相容的 unordered_set 中提取的節點。


依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

刪除前,position 後面的迭代器。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。


按值刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& x);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。


快速刪除 (quick_erase)
void quick_erase(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


erase_return_void
void erase_return_void(const_iterator position);

刪除 position 所指向的元素。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。

注意

實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。


交換 (swap)
void swap(unordered_multiset&)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value &&
           boost::is_nothrow_swappable_v<Hash> &&
           boost::is_nothrow_swappable_v<Pred>);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0

拋出

永遠不會擲出例外。


合併 (merge)
template<class H2, class P2>
  void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);
template<class H2, class P2>
  void merge(unordered_set<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_set<Key, H2, P2, Allocator>&& source);

嘗試透過迭代 source 並提取 source 中的所有節點並將其插入到 *this 中來「合併」兩個容器。

因為 source 可以具有不同的雜湊函數和鍵相等述詞,所以 source 中每個節點的鍵都會使用 this->hash_function() 重新雜湊,然後,如果需要,則使用 this->key_eq() 比較。

如果 this->get_allocator() != source.get_allocator(),則此函數的行為未定義。

此函數不會複製或移動任何元素,而是單純將節點從 source 重新定位到 *this 中。

注意
  • 指向和引用已傳輸元素的指標和參考保持有效。

  • 使指向已傳輸元素的迭代器失效。

  • 使屬於 *this 的迭代器失效。

  • 指向 source 中未傳輸元素的迭代器保持有效。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;

hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
template<class K>
  const_iterator find(const K& k) const;
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  iterator       find(CompatibleKey const&, CompatibleHash const&,
                      CompatiblePredicate const&);
template<typename CompatibleKey, typename CompatibleHash, typename CompatiblePredicate>
  const_iterator  find(CompatibleKey const&, CompatibleHash const&,
                       CompatiblePredicate const&) const;
傳回

指向具有與 k 等價鍵的元素的迭代器,如果不存在此類元素,則為 b.end()

注意

包含 CompatibleKeyCompatibleHashCompatiblePredicate 的樣板多載是非標準擴充功能,可讓您使用相容的雜湊函數和相等述詞,來處理不同類型的鍵,以避免昂貴的類型轉換。一般來說,不鼓勵使用它,而應使用 K 成員函數樣板。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

桶子的數量。


max_bucket_count
size_type max_bucket_count() const noexcept;
傳回

桶子數量的上限。


bucket_size
size_type bucket_size(size_type n) const;
需求

n < bucket_count()

傳回

桶子 n 中的元素數量。


儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回

將包含鍵為 k 的元素的儲存桶的索引。

後置條件

回傳值小於 bucket_count()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的本機迭代器。


end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的本機迭代器。


cbegin
const_local_iterator cbegin(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中第一個元素的常數本機迭代器。


cend
const_local_iterator cend(size_type n) const;
需求

n 應在範圍 [0, bucket_count()) 內。

傳回

指向索引為 n 的儲存桶中「超出末尾」元素的常數本機迭代器。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

每個儲存桶的平均元素數量。


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

回傳目前的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

變更容器的最大負載因子,使用 z 作為提示。


重新雜湊 (rehash)
void rehash(size_type n);

變更儲存桶數量,使其至少有 n 個儲存桶,且載入因子小於或等於最大載入因子。在適用的情況下,這會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor())),或者如果 n > 0a.max_load_factor() == std::numeric_limits<float>::infinity(),則等同於 a.rehash(1)

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效,並變更元素的順序。指向元素的指標和參考不會失效。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& x,
                  const unordered_multiset<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_multiset<Key, Hash, Pred, Alloc>& x,
                  const unordered_multiset<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


交換

template<class Key, class Hash, class Pred, class Alloc>
  void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x,
            unordered_multiset<Key, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 的複製建構函式或複製賦值運算子擲出例外,否則不會擲出例外。

注意

例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。


erase_if

template<class K, class H, class P, class A, class Predicate>
  typename unordered_multiset<K, H, P, A>::size_type
    erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

unordered_multiset 可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。

將 unordered_multiset 儲存到封存檔

unordered_multiset x 的所有元素儲存到封存檔 (XML 封存檔) ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。


從封存檔載入 unordered_multiset

刪除 unordered_multiset x 的所有先前存在的元素,並從封存檔 (XML 封存檔) ar 插入還原的原始 unordered_multiset other 的元素副本,這些副本儲存在 ar 讀取的儲存空間中。

需求

value_type可移動插入 (MoveInsertable) 的。x.key_equal() 的功能與 other.key_equal() 等效。

注意

如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 BOOST_UNORDERED_ENABLE_SERIALIZATION_COMPATIBILITY_V0,此操作才能成功;否則會擲回例外。


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_multiset x 之前已儲存到 ar,並且在儲存 x 和儲存 it 之間,未對 x 執行任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_multiset,則在載入 x 和載入 it 之間,未對 x 執行任何修改操作。

雜湊特性

概要

// #include <boost/unordered/hash_traits.hpp>

namespace boost {
namespace unordered {

template<typename Hash>
struct hash_is_avalanching;

} // namespace unordered
} // namespace boost

hash_is_avalanching

template<typename Hash>
struct hash_is_avalanching;

如果輸入中的小變動轉換為返回的雜湊碼中的大變動,則稱雜湊函數具有雪崩效應 — 理想情況下,翻轉輸入值表示中的一個位元會導致雜湊碼的每個位元以 50% 的機率翻轉。接近此特性對於開放定址雜湊容器的正常行為至關重要。

hash_is_avalanching<Hash>::value

  • 如果不存在 Hash::is_avalanching,則為 false

  • 如果存在且在編譯時可轉換為 bool,則為 Hash::is_avalanching::value

  • 如果 Hash::is_avalanchingvoid (不建議使用此用法),則為 true

  • 否則格式不正確。

然後,使用者可以透過在 Hash 的定義中嵌入適當的 is_avalanching typedef,或者直接將 hash_is_avalanching<Hash> 特製化為具有嵌入的編譯時期常數 value 並設定為 true 的類別,來宣告雜湊函數 Hash 為雪崩式。

如果 hash_is_avalanching<Hash>::valuetrue,則開放定址和並行容器會按原樣使用提供的雜湊函數 Hash;否則,它們會實作位元混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


統計

可以將開放定址和並行容器設定為保留受所提供的雜湊函數品質影響的某些內部操作的執行統計資訊。

概要

struct stats-summary-type
{
  double average;
  double variance;
  double deviation;
};

struct insertion-stats-type
{
  std::size_t        count;
  stats-summary-type probe_length;
};

struct lookup-stats-type
{
  std::size_t        count;
  stats-summary-type probe_length;
  stats-summary-type num_comparisons;
};

struct stats-type
{
  insertion-stats-type insertion;
  lookup-stats-type    successful_lookup,
                       unsuccessful_lookup;
};
統計資料摘要類型

提供數值序列的平均值、變異數和標準差。

插入統計資料類型

提供容器執行的插入操作次數以及相關的探測長度 (每個操作存取的儲存桶群組數) 的統計資訊。

查詢統計資料類型

對於成功 (找到元素) 或不成功 (未找到) 的查詢,提供容器執行的操作次數以及相關的探測長度 (存取的儲存桶群組數) 和每個操作的元素比較次數的統計資訊。

統計資料類型

提供容器執行的插入、成功和不成功的查詢統計資訊。如果提供的雜湊函數具有良好的品質,則

  • 平均探測長度應接近 1.0。

  • 對於成功的查詢,平均元素比較次數應接近 1.0。

  • 對於查找失敗的情況,元素比較的平均次數應該接近 0.0。

這些統計數據可用於判斷給定的雜湊函數是否可以標記為 雪崩效應


類別模板 unordered_flat_map

boost::unordered_flat_map — 一個開放定址的非排序關聯容器,將唯一的鍵與另一個值關聯起來。

boost::unordered_flat_map 的效能比 boost::unordered_map 或其他 std::unordered_map 的實作要好得多。與基於節點的標準非排序關聯容器不同,boost::unordered_flat_map 的元素直接保存在儲存桶陣列中,並且插入到已佔用的儲存桶中的操作會轉移到原始位置附近可用的儲存桶。這種資料佈局類型稱為開放定址

由於使用開放定址,boost::unordered_flat_map 的介面在許多方面與 boost::unordered_map/std::unordered_map 的介面有所不同

  • value_type 必須是可移動建構的。

  • 指標穩定性在重新雜湊時不會保持。

  • begin() 不是常數時間。

  • 沒有用於儲存桶處理的 API(除了 bucket_count)或節點提取/插入。

  • 容器的最大負載因子由內部管理,使用者無法設定。

除此之外,boost::unordered_flat_map 大部分可以作為基於節點的標準非排序關聯容器的直接替代品。

概要

// #include <boost/unordered/unordered_flat_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class unordered_flat_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using init_type            = std::pair<
                                   typename std::remove_const<Key>::type,
                                   typename std::remove_const<T>::type
                                 >;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // construct/copy/destroy
    unordered_flat_map();
    explicit unordered_flat_map(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_flat_map(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_flat_map(const unordered_flat_map& other);
    unordered_flat_map(unordered_flat_map&& other);
    template<class InputIterator>
      unordered_flat_map(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_flat_map(const Allocator& a);
    unordered_flat_map(const unordered_flat_map& other, const Allocator& a);
    unordered_flat_map(unordered_flat_map&& other, const Allocator& a);
    unordered_flat_map(concurrent_flat_map<Key, T, Hash, Pred, Allocator>&& other);
    unordered_flat_map(std::initializer_list<value_type> il,
                       size_type n = implementation-defined
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_flat_map(size_type n, const allocator_type& a);
    unordered_flat_map(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_flat_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_flat_map(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_flat_map(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a);
    unordered_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_flat_map();
    unordered_flat_map& operator=(const unordered_flat_map& other);
    unordered_flat_map& operator=(unordered_flat_map&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    unordered_flat_map& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(const init_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    std::pair<iterator, bool> insert(init_type&& obj);
    iterator       insert(const_iterator hint, const value_type& obj);
    iterator       insert(const_iterator hint, const init_type& obj);
    iterator       insert(const_iterator hint, value_type&& obj);
    iterator       insert(const_iterator hint, init_type&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);

    template<class... Args>
      std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      std::pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    convertible-to-iterator     erase(iterator position);
    convertible-to-iterator     erase(const_iterator position);
    size_type                   erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_flat_map& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_flat_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_flat_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // element access
    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    template<class K> mapped_type& operator[](K&& k);
    mapped_type& at(const key_type& k);
    const mapped_type& at(const key_type& k) const;
    template<class K> mapped_type& at(const K& k);
    template<class K> const mapped_type& at(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    unordered_flat_map(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            Pred, Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    unordered_flat_map(std::initializer_list<std::pair<Key, T>>,
                       typename see below::size_type = see below, Hash = Hash(),
                       Pred = Pred(), Allocator = Allocator())
      -> unordered_flat_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_flat_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_flat_map(InputIterator, InputIterator, Allocator)
      -> unordered_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_flat_map(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_flat_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Allocator)
      -> unordered_flat_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_flat_map(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> unordered_flat_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_flat_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Hash, Allocator)
      -> unordered_flat_map<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_flat_map<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_flat_map<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
              unordered_flat_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_flat_map<K, T, H, P, A>::size_type
       erase_if(unordered_flat_map<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_flat_map =
      boost::unordered_flat_map<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

KeyT 必須是 可移動建構的。std::pair<const Key, T> 必須可以從任何可轉換為它的 std::pair 物件就地建構到容器中,並且也必須可以從容器中清除

T

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

容器的元素保存在內部儲存桶陣列中。一個元素會插入到由其雜湊碼確定的儲存桶中,但如果該儲存桶已被佔用(發生碰撞),則會使用原始位置附近可用的儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或者透過呼叫 rehash/reserve 增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor(),除非在實作決定允許更高負載的小尺寸情況下。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


組態巨集

BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集以啟用容器的統計計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined iterator;

值類型為 value_type 的迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

建構子

預設建構函式
unordered_flat_map();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞和 allocator_type() 作為配置器,建構一個空的容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_flat_map(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_flat_map(InputIterator f, InputIterator l,
                     size_type n = implementation-defined,
                     const hasher& hf = hasher(),
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_flat_map(unordered_flat_map const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_flat_map(unordered_flat_map&& other);

移動建構子。other 的內部儲存桶陣列會直接轉移到新的容器。雜湊函數、述詞和配置器會從 other 移動建構。如果啟用統計資料,則會從 other 轉移內部統計資訊並呼叫 other.reset_stats()


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_flat_map(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_flat_map(Allocator const& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_flat_map(unordered_flat_map const& other, Allocator const& a);

建構一個容器,複製 other 包含的元素、雜湊函數和述詞,但使用配置器 a


具備配置器的移動建構子
unordered_flat_map(unordered_flat_map&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接轉移到新的容器;否則,元素會從 other 的元素移動建構。雜湊函數和述詞會從 other 移動建構,而配置器會從 a 複製建構。如果 啟用 統計資料,則僅在 a == other.get_allocator() 時,才會從 other 轉移內部統計資訊,並始終呼叫 other.reset_stats()


從 concurrent_flat_map 移動建構子
unordered_flat_map(concurrent_flat_map<Key, T, Hash, Pred, Allocator>&& other);

concurrent_flat_map 移動建構。other 的內部儲存桶陣列會直接轉移到新的容器。雜湊函數、述詞和配置器會從 other 移動建構。如果啟用統計資料,則會從 other 轉移內部統計資訊並呼叫 other.reset_stats()

複雜度

常數時間。

並行性

other 上鎖定。


初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il,
              size_type n = implementation-defined
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_flat_map(size_type n, allocator_type const& a);

使用 hf 作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_flat_map(size_type n, hasher const& hf, allocator_type const& a);

使用 hf 作為雜湊函數、預設的鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      unordered_flat_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                   const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_flat_map();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_flat_map& operator=(unordered_flat_map const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入


移動賦值
unordered_flat_map& operator=(unordered_flat_map&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動賦值運算子。銷毀先前存在的元素,交換 other 的雜湊函數和述詞,如果存在 Alloc::propagate_on_container_move_assignmentAlloc::propagate_on_container_move_assignment::valuetrue,則從 other 移動賦值配置器。如果此時配置器等於 other.get_allocator(),則 other 的內部儲存桶陣列會直接轉移到新的容器;否則,會插入 other 元素的移動建構副本。如果 啟用 統計資料,則僅在最終配置器等於 other.get_allocator() 時,才會從 other 轉移內部統計資訊,並始終呼叫 other.reset_stats()


初始化列表賦值
unordered_flat_map& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


end
iterator end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素,僅使用 k 引數進行檢查。


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

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

position 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素,僅使用 k 引數進行檢查。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);
std::pair<iterator, bool> insert(const init_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);
std::pair<iterator, bool> insert(init_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, const init_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

形式為 insert(hint, x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
iterator insert(const_iterator hint, init_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

形式為 insert(hint, x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可以從 *first 就地建構到容器中。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


try_emplace
template<class... Args>
  std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class K, class... Args>
  std::pair<iterator, bool> try_emplace(K&& k, Args&&... args);

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函式類似於 emplace,不同之處在於,如果存在具有等效鍵的元素,則不會建構 value_type;否則,建構形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace 不同,後者只是將所有引數轉發到 value_type 的建構子。

可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 try_emplace
template<class... Args>
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args>
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
template<class K, class... Args>
  iterator try_emplace(const_iterator hint, K&& k, Args&&... args);

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函式類似於 emplace_hint,不同之處在於,如果存在具有等效鍵的元素,則不會建構 value_type;否則,建構形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace_hint 不同,後者只是將所有引數轉發到 value_type 的建構子。

可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


insert_or_assign
template<class M>
  std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class K, class M>
  std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))
傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 insert_or_assign
template<class M>
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M>
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

一個不透明物件,可以隱式轉換為刪除前緊接在 position 之後的 iteratorconst_iterator

拋出

無。

注意

傳回的不透明物件只能被捨棄或立即轉換為 iteratorconst_iterator


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

在此實作中無任何作用(不會呼叫 hasherkey_equal 物件)。


交換 (swap)
void swap(unordered_flat_map& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()


合併 (merge)
template<class H2, class P2>
  void merge(unordered_flat_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_flat_map<Key, T, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

容器的配置器。


hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
傳回

指向鍵值與 k 相等的元素的迭代器,如果不存在此類元素,則返回 end()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用

如果容器尚未包含鍵值與 k 相等的元素,則插入值 std::pair<key_type const, mapped_type>(k, mapped_type())

傳回

x.second 的參考,其中 x 是容器中已存在的元素,或是具有與 k 等價鍵的新插入元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


at
mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
template<class K> mapped_type& at(const K& k);
template<class K> const mapped_type& at(const K& k) const;
傳回

x.second 的參考,其中 x 是(唯一)鍵與 k 等價的元素。

拋出

如果不存在此類元素,則擲出類型為 std::out_of_range 的例外物件。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回容器的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_map 相容。


max_load
size_type max_load() const noexcept;
傳回

容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。

注意

建構、重新雜湊或清除後,容器的最大負載至少為 max_load_factor() * bucket_count()。在高負載情況下刪除元素時,此數值可能會減少。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,並且負載因子小於或等於最大負載因子。在適用的情況下,這將會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 將會釋放底層的儲存桶陣列。如果提供的配置器使用花俏指標,則後續會執行預設配置。

使迭代器、指標和參考失效,並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器、指標和參考失效,並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


統計

get_stats
stats get_stats() const;
傳回

容器目前為止執行的插入和查找操作的統計描述。

注意

僅在 統計資料計算 啟用 時可用。


reset_stats
void reset_stats() noexcept;
作用

將容器保留的內部統計資料設為零。

注意

僅在 統計資料計算 啟用 時可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_flat_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_flat_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。

交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_flat_map<Key, T, Hash, Pred, Alloc>& x,
            unordered_flat_map<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_flat_map<K, T, H, P, A>::size_type
    erase_if(unordered_flat_map<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 unordered_flat_map。支援一般和 XML 封存。

將 unordered_flat_map 儲存至封存

unordered_flat_map x 的所有元素儲存到封存 (XML 封存) ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。


從封存載入 unordered_flat_map

刪除 unordered_flat_map x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入還原的 unordered_flat_map other 元素的副本,這些副本已儲存至 ar 讀取的儲存空間。

需求

x.key_equal() 在功能上等同於 other.key_equal()


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 指向的 unordered_flat_map x 先前已儲存至 ar,並且在儲存 x 和儲存 it 之間未對 x 發出任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 指向的 unordered_flat_map,則在載入 x 和載入 it 之間未對 x 發出任何修改操作。

類別模板 unordered_flat_set

boost::unordered_flat_set — 一個開放定址無序關聯容器,用於儲存唯一值。

boost::unordered_flat_set 的效能比 boost::unordered_set 或其他 std::unordered_set 實作要好得多。與標準的無序關聯容器 (以節點為基礎) 不同,boost::unordered_flat_set 的元素直接保留在儲存桶陣列中,而插入已佔用儲存桶的元素會轉移至原始位置附近的可用儲存桶。這種資料配置類型稱為「開放定址」。

由於使用開放定址,boost::unordered_flat_set 的介面在許多方面與 boost::unordered_flat_set/std::unordered_flat_set 的介面有所不同。

  • value_type 必須是可移動建構的。

  • 指標穩定性在重新雜湊時不會保持。

  • begin() 不是常數時間。

  • 沒有用於儲存桶處理的 API(除了 bucket_count)或節點提取/插入。

  • 容器的最大負載因子由內部管理,使用者無法設定。

除此之外,boost::unordered_flat_set 大致上是節點式標準無序關聯容器的直接替代品。

概要

// #include <boost/unordered/unordered_flat_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class unordered_flat_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using init_type            = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // construct/copy/destroy
    unordered_flat_set();
    explicit unordered_flat_set(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_flat_set(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_flat_set(const unordered_flat_set& other);
    unordered_flat_set(unordered_flat_set&& other);
    template<class InputIterator>
      unordered_flat_set(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_flat_set(const Allocator& a);
    unordered_flat_set(const unordered_flat_set& other, const Allocator& a);
    unordered_flat_set(concurrent_flat_set<Key, Hash, Pred, Allocator>&& other);
    unordered_flat_set(std::initializer_list<value_type> il,
                       size_type n = implementation-defined
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_flat_set(size_type n, const allocator_type& a);
    unordered_flat_set(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_flat_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_flat_set(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_flat_set(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a);
    unordered_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_flat_set();
    unordered_flat_set& operator=(const unordered_flat_set& other);
    unordered_flat_set& operator=(unordered_flat_set&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    unordered_flat_set& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    template<class K> std::pair<iterator, bool> insert(K&& k);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class K> iterator insert(const_iterator hint, K&& k);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);

    convertible-to-iterator     erase(iterator position);
    convertible-to-iterator     erase(const_iterator position);
    size_type                   erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_flat_set& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_flat_set<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_flat_set<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    unordered_flat_set(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_flat_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    unordered_flat_set(std::initializer_list<T>, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_flat_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_flat_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_flat_set<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_flat_set(InputIterator, InputIterator, Allocator)
      -> unordered_flat_set<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_flat_set(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_flat_set<iter-value-type<InputIterator>, Hash,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    unordered_flat_set(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    unordered_flat_set(std::initializer_list<T>, Allocator)
      -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_flat_set(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_flat_set<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_flat_set<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_flat_set<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
              unordered_flat_set<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_flat_set<K, T, H, P, A>::size_type
       erase_if(unordered_flat_set<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_flat_set =
      boost::unordered_flat_set<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可 移動插入 至容器中,且可從容器中 抹除

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

容器的元素保存在內部儲存桶陣列中。一個元素會插入到由其雜湊碼確定的儲存桶中,但如果該儲存桶已被佔用(發生碰撞),則會使用原始位置附近可用的儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或者透過呼叫 rehash/reserve 增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor(),除非在實作決定允許更高負載的小尺寸情況下。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


組態巨集

BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集以啟用容器的統計計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

建構子

預設建構函式
unordered_flat_set();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞和 allocator_type() 作為配置器,建構一個空的容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_flat_set(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_flat_set(InputIterator f, InputIterator l,
                     size_type n = implementation-defined,
                     const hasher& hf = hasher(),
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_flat_set(unordered_flat_set const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_flat_set(unordered_flat_set&& other);

移動建構函式。other 的內部儲存桶陣列會直接傳輸至新的容器。雜湊函式、述詞和配置器是從 other 移動建構而來。如果 啟用 統計資料,則會將內部統計資訊從 other 傳輸,並呼叫 other.reset_stats()


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_flat_set(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_flat_set(Allocator const& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_flat_set(unordered_flat_set const& other, Allocator const& a);

建構一個容器,複製 other 包含的元素、雜湊函數和述詞,但使用配置器 a


具備配置器的移動建構子
unordered_flat_set(unordered_flat_set&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接傳輸至新的容器;否則,元素會從 other 的元素移動建構而來。雜湊函式和述詞是從 other 移動建構而來,而配置器是從 a 複製建構而來。如果 啟用 統計資料,則僅當 a == other.get_allocator() 時才會從 other 傳輸內部統計資訊,並且一律呼叫 other.reset_stats()


從 concurrent_flat_set 移動建構函式
unordered_flat_set(concurrent_flat_set<Key, Hash, Pred, Allocator>&& other);

concurrent_flat_set 移動建構而來。other 的內部儲存桶陣列會直接傳輸至新的容器。雜湊函式、述詞和配置器是從 other 移動建構而來。如果 啟用 統計資料,則會將內部統計資訊從 other 傳輸,並呼叫 other.reset_stats()

複雜度

常數時間。

並行性

other 上鎖定。


初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il,
              size_type n = implementation-defined
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_flat_set(size_type n, allocator_type const& a);

使用 hf 作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_flat_set(size_type n, hasher const& hf, allocator_type const& a);

使用 hf 作為雜湊函數、預設的鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      unordered_flat_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                   const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_flat_set();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_flat_set& operator=(unordered_flat_set const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入


移動賦值
unordered_flat_set& operator=(unordered_flat_set&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動指派運算子。銷毀先前存在的元素、從 other 交換雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則從 other 移動指派配置器。如果此時配置器等於 other.get_allocator(),則 other 的內部儲存桶陣列會直接傳輸至新的容器;否則,會插入 other 元素的移動建構副本。如果 啟用 統計資料,則僅當最終配置器等於 other.get_allocator() 時才會從 other 傳輸內部統計資訊,並且一律呼叫 other.reset_stats()


初始化列表賦值
unordered_flat_set& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


end
iterator end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


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

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

position 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


具有提示的透明插入
template<class K> std::pair<iterator, bool> insert(const_iterator hint, K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可以從 *first 就地建構到容器中。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。


依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

一個不透明物件,可以隱式轉換為刪除前緊接在 position 之後的 iteratorconst_iterator

拋出

無。

注意

傳回的不透明物件只能被捨棄或立即轉換為 iteratorconst_iterator


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

在此實作中無任何作用(不會呼叫 hasherkey_equal 物件)。


交換 (swap)
void swap(unordered_flat_set& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()


合併 (merge)
template<class H2, class P2>
  void merge(unordered_flat_set<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_flat_set<Key, T, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

容器的配置器。


hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
傳回

指向鍵值與 k 相等的元素的迭代器,如果不存在此類元素,則返回 end()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回容器的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_set 相容。


max_load
size_type max_load() const noexcept;
傳回

容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。

注意

建構、重新雜湊或清除後,容器的最大負載至少為 max_load_factor() * bucket_count()。在高負載情況下刪除元素時,此數值可能會減少。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,並且負載因子小於或等於最大負載因子。在適用的情況下,這將會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 將會釋放底層的儲存桶陣列。如果提供的配置器使用花俏指標,則後續會執行預設配置。

使迭代器、指標和參考失效,並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器、指標和參考失效,並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


統計

get_stats
stats get_stats() const;
傳回

容器目前為止執行的插入和查找操作的統計描述。

注意

僅在 統計資料計算 啟用 時可用。


reset_stats
void reset_stats() noexcept;
作用

將容器保留的內部統計資料設為零。

注意

僅在 統計資料計算 啟用 時可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_flat_set<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_flat_set<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。

交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_flat_set<Key, T, Hash, Pred, Alloc>& x,
            unordered_flat_set<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_flat_set<K, T, H, P, A>::size_type
    erase_if(unordered_flat_set<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 unordered_flat_set。支援一般和 XML 封存。

將 unordered_flat_set 儲存至封存

unordered_flat_set x 的所有元素儲存到封存 (XML 封存) ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。


從封存載入 unordered_flat_set

刪除 unordered_flat_set x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入還原的 unordered_flat_set other 元素的副本,這些副本已儲存至 ar 讀取的儲存空間。

需求

x.key_equal() 在功能上等同於 other.key_equal()


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 指向的 unordered_flat_set x 先前已儲存至 ar,並且在儲存 x 和儲存 it 之間未對 x 發出任何修改操作。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 指向的 unordered_flat_set,則在載入 x 和載入 it 之間未對 x 發出任何修改操作。

類別模板 unordered_node_map

boost::unordered_node_map — 一個以節點為基礎的開放定址無序關聯容器,可將唯一鍵值與另一個值建立關聯。

boost::unordered_node_map 使用與 boost::unordered_flat_map 相同的開放定址配置,但由於以節點為基礎,因此提供指標穩定性和節點處理功能。其效能介於 boost::unordered_mapboost::unordered_flat_map 之間。

由於使用開放定址,boost::unordered_node_map 的介面在許多方面與 boost::unordered_map/std::unordered_map 的介面有所不同。

  • begin() 不是常數時間。

  • 沒有用於儲存桶處理的 API(除了 bucket_count)。

  • 容器的最大負載因子由內部管理,使用者無法設定。

除此之外,boost::unordered_node_map 大致上是標準無序關聯容器的直接替代品。

概要

// #include <boost/unordered/unordered_node_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class unordered_node_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using init_type            = std::pair<
                                   typename std::remove_const<Key>::type,
                                   typename std::remove_const<T>::type
                                 >;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;

    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // construct/copy/destroy
    unordered_node_map();
    explicit unordered_node_map(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_node_map(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_node_map(const unordered_node_map& other);
    unordered_node_map(unordered_node_map&& other);
    template<class InputIterator>
      unordered_node_map(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_node_map(const Allocator& a);
    unordered_node_map(const unordered_node_map& other, const Allocator& a);
    unordered_node_map(unordered_node_map&& other, const Allocator& a);
    unordered_node_map(concurrent_node_map<Key, T, Hash, Pred, Allocator>&& other);
    unordered_node_map(std::initializer_list<value_type> il,
                       size_type n = implementation-defined
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_node_map(size_type n, const allocator_type& a);
    unordered_node_map(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_node_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_node_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_node_map(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_node_map(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a);
    unordered_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_node_map();
    unordered_node_map& operator=(const unordered_node_map& other);
    unordered_node_map& operator=(unordered_node_map&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    unordered_node_map& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(const init_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    std::pair<iterator, bool> insert(init_type&& obj);
    iterator       insert(const_iterator hint, const value_type& obj);
    iterator       insert(const_iterator hint, const init_type& obj);
    iterator       insert(const_iterator hint, value_type&& obj);
    iterator       insert(const_iterator hint, init_type&& obj);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);
    insert_return_type insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    template<class... Args>
      std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template<class... Args>
      std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args>
      std::pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template<class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template<class M>
      std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M>
      std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template<class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
    template<class K, class M>
      iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

    convertible-to-iterator     erase(iterator position);
    convertible-to-iterator     erase(const_iterator position);
    size_type                   erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_node_map& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    node_type extract(const_iterator position);
    node_type extract(const key_type& key);
    template<class K> node_type extract(K&& key);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_node_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_node_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // element access
    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    template<class K> mapped_type& operator[](K&& k);
    mapped_type& at(const key_type& k);
    const mapped_type& at(const key_type& k) const;
    template<class K> mapped_type& at(const K& k);
    template<class K> const mapped_type& at(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    unordered_node_map(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            Pred, Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    unordered_node_map(std::initializer_list<std::pair<Key, T>>,
                       typename see below::size_type = see below, Hash = Hash(),
                       Pred = Pred(), Allocator = Allocator())
      -> unordered_node_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_node_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_node_map(InputIterator, InputIterator, Allocator)
      -> unordered_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                            boost::hash<iter-key-type<InputIterator>>,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_node_map(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                            std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_node_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Allocator)
      -> unordered_node_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    unordered_node_map(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> unordered_node_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_node_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                       Hash, Allocator)
      -> unordered_node_map<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_node_map<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_node_map<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
              unordered_node_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_node_map<K, T, H, P, A>::size_type
       erase_if(unordered_node_map<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_node_map =
      boost::unordered_node_map<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

std::pair<const Key, T> 必須可從任何可轉換為它的 std::pair 物件 就地建構 至容器中,而且也必須可從容器中 抹除

T

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

容器的元素節點會保留在內部「儲存桶陣列」中。節點會插入由其元素雜湊碼決定的儲存桶中,但如果該儲存桶已被佔用 (發生「衝突」),則會使用原始位置附近的可用儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或者透過呼叫 rehash/reserve 增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor(),除非在實作決定允許更高負載的小尺寸情況下。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


組態巨集

BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集以啟用容器的統計計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined iterator;

值類型為 value_type 的迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined node_type;

一個用於保存提取的容器元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class Iterator, class NodeType>
struct insert_return_type // name is exposition only
{
  Iterator position;
  bool     inserted;
  NodeType node;
};

其中 Iterator = iteratorNodeType = node_type


建構子

預設建構函式
unordered_node_map();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞和 allocator_type() 作為配置器,建構一個空的容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_node_map(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_node_map(InputIterator f, InputIterator l,
                     size_type n = implementation-defined,
                     const hasher& hf = hasher(),
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_node_map(unordered_node_map const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。


移動建構函式
unordered_node_map(unordered_node_map&& other);

移動建構函式。other 的內部儲存桶陣列會直接傳輸至新的容器。雜湊函式、述詞和配置器是從 other 移動建構而來。如果 啟用 統計資料,則會將內部統計資訊從 other 傳輸,並呼叫 other.reset_stats()


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_node_map(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_node_map(Allocator const& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_node_map(unordered_node_map const& other, Allocator const& a);

建構一個容器,複製 other 包含的元素、雜湊函數和述詞,但使用配置器 a


具備配置器的移動建構子
unordered_node_map(unordered_node_map&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素節點會直接傳輸至新的容器;否則,元素會從 other 的元素移動建構而來。雜湊函式和述詞是從 other 移動建構而來,而配置器是從 a 複製建構而來。如果 啟用 統計資料,則僅當 a == other.get_allocator() 時才會從 other 傳輸內部統計資訊,並且一律呼叫 other.reset_stats()


從 concurrent_node_map 移動建構函式
unordered_node_map(concurrent_node_map<Key, T, Hash, Pred, Allocator>&& other);

concurrent_node_map 移動建構而來。other 的內部儲存桶陣列會直接傳輸至新的容器。雜湊函式、述詞和配置器是從 other 移動建構而來。如果 啟用 統計資料,則會將內部統計資訊從 other 傳輸,並呼叫 other.reset_stats()

複雜度

常數時間。

並行性

other 上鎖定。


初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il,
              size_type n = implementation-defined
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_node_map(size_type n, allocator_type const& a);

使用 hf 作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_node_map(size_type n, hasher const& hf, allocator_type const& a);

使用 hf 作為雜湊函數、預設的鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_node_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      unordered_node_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                   const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_node_map();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_node_map& operator=(unordered_node_map const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入


移動賦值
unordered_node_map& operator=(unordered_node_map&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動指派運算子。銷毀先前存在的元素、從 other 交換雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則從 other 移動指派配置器。如果此時配置器等於 other.get_allocator(),則 other 的內部儲存桶陣列會直接傳輸至新的容器;否則,會插入 other 元素的移動建構副本。如果 啟用 統計資料,則僅當最終配置器等於 other.get_allocator() 時才會從 other 傳輸內部統計資訊,並且一律呼叫 other.reset_stats()


初始化列表賦值
unordered_node_map& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


end
iterator end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素時,才僅使用 k 引數進行檢查。當 key_type 可移動建構,或者當 k 引數為 key_type 時,就會發生此最佳化。


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

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

position 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素時,才僅使用 k 引數進行檢查。當 key_type 可移動建構,或者當 k 引數為 key_type 時,就會發生此最佳化。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);
std::pair<iterator, bool> insert(const init_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);
std::pair<iterator, bool> insert(init_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, const init_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

形式為 insert(hint, x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
iterator insert(const_iterator hint, init_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

形式為 insert(hint, x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可以從 *first 就地建構到容器中。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


插入節點
insert_return_type insert(node_type&& nh);

如果 nh 不為空,則僅當容器中沒有鍵值與 nh.key() 相等的元素時,才會在容器中插入關聯元素。當函式傳回時,nh 為空。

傳回

一個由 positioninsertednode 建構而成的 insert_return_type 物件

  • 如果 nh 是空的,則 insertedfalsepositionend(),且 node 為空。

  • 否則,如果插入成功,則 inserted 為 true,position 指向插入的元素,且 node 為空。

  • 如果插入失敗,則 inserted 為 false,node 具有 nh 的先前值,且 position 指向具有與 nh.key() 等效鍵的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


使用提示插入節點
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 不為空,則當且僅當容器中沒有與 nh.key() 等效鍵的元素時,才將關聯的元素插入容器。如果插入成功,nh 會變為空,否則不會變更。

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果 nh 為空,則傳回的迭代器為 end()。如果插入成功,則迭代器指向新插入的元素;否則,它指向具有等效鍵的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


try_emplace
template<class... Args>
  std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
template<class... Args>
  std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
template<class K, class... Args>
  std::pair<iterator, bool> try_emplace(K&& k, Args&&... args);

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函式類似於 emplace,不同之處在於,如果存在具有等效鍵的元素,則不會建構 value_type;否則,建構形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace 不同,後者只是將所有引數轉發給 value_type 的建構函式。

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 try_emplace
template<class... Args>
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
template<class... Args>
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
template<class K, class... Args>
  iterator try_emplace(const_iterator hint, K&& k, Args&&... args);

如果容器中沒有具有鍵值 k 的現有元素,則將新元素插入到容器中。

如果存在具有鍵值 k 的現有元素,則此函數不會執行任何動作。

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

此函式類似於 emplace_hint,不同之處在於,如果存在具有等效鍵的元素,則不會建構 value_type;否則,建構形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace_hint 不同,後者只是將所有引數轉發給 value_type 的建構函式。

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K, class... Args> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


insert_or_assign
template<class M>
  std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
template<class M>
  std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
template<class K, class M>
  std::pair<iterator, bool> insert_or_assign(K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))
傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


具備提示的 insert_or_assign
template<class M>
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
template<class M>
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
template<class K, class M>
  iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);

將新元素插入到容器中,或透過賦值到包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有這樣的元素,則將它作為以下項目新增至容器:

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

一個不透明物件,可以隱式轉換為刪除前緊接在 position 之後的 iteratorconst_iterator

拋出

無。

注意

傳回的不透明物件只能被捨棄或立即轉換為 iteratorconst_iterator


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

在此實作中無任何作用(不會呼叫 hasherkey_equal 物件)。


交換 (swap)
void swap(unordered_node_map& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


依位置提取
node_type extract(const_iterator position);

提取 position 所指向的元素。

傳回

一個包含提取元素的 node_type 物件。

拋出

無。


透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

提取具有與 k 等效鍵的元素(如果存在)。

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()


合併 (merge)
template<class H2, class P2>
  void merge(unordered_node_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_node_map<Key, T, H2, P2, Allocator>&& source);

source 中所有鍵未出現在 *this 中的元素節點傳輸過來。

需求

this->get_allocator() == source.get_allocator().

注意

使傳輸元素的迭代器失效。如果 *this 的結果大小大於其原始最大負載,則使與 *this 關聯的所有迭代器失效。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

容器的配置器。


hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
傳回

指向鍵值與 k 相等的元素的迭代器,如果不存在此類元素,則返回 end()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用

如果容器尚未包含鍵值與 k 相等的元素,則插入值 std::pair<key_type const, mapped_type>(k, mapped_type())

傳回

x.second 的參考,其中 x 是容器中已存在的元素,或是具有與 k 等價鍵的新插入元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


at
mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
template<class K> mapped_type& at(const K& k);
template<class K> const mapped_type& at(const K& k) const;
傳回

x.second 的參考,其中 x 是(唯一)鍵與 k 等價的元素。

拋出

如果不存在此類元素,則擲出類型為 std::out_of_range 的例外物件。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回容器的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_map 相容。


max_load
size_type max_load() const noexcept;
傳回

容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。

注意

建構、重新雜湊或清除後,容器的最大負載至少為 max_load_factor() * bucket_count()。在高負載情況下刪除元素時,此數值可能會減少。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,並且負載因子小於或等於最大負載因子。在適用的情況下,這將會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 將會釋放底層的儲存桶陣列。如果提供的配置器使用花俏指標,則後續會執行預設配置。

使迭代器失效並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


統計

get_stats
stats get_stats() const;
傳回

容器目前為止執行的插入和查找操作的統計描述。

注意

僅當 統計資料計算 啟用時才可用。


reset_stats
void reset_stats() noexcept;
作用

將容器保留的內部統計資料設為零。

注意

僅當 統計資料計算 啟用時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_node_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_node_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。

交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_node_map<Key, T, Hash, Pred, Alloc>& x,
            unordered_node_map<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_node_map<K, T, H, P, A>::size_type
    erase_if(unordered_node_map<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

可以透過此程式庫提供的 API,使用 Boost.Serialization 封存/擷取 unordered_node_map。支援常規和 XML 封存。

將 unordered_node_map 儲存到封存

unordered_node_map x 的所有元素儲存到封存 (XML 封存) ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。


從封存載入 unordered_node_map

刪除 unordered_node_map x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入儲存在 ar 讀取儲存區的原始 unordered_node_map other 元素的還原副本。

需求

key_typemapped_type 分別可從 std::remove_const<key_type>::type&&std::remove_const<mapped_type>::type&& 建構。 x.key_equal() 在功能上等效於 other.key_equal()


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_node_map x 先前已儲存至 ar,且在儲存 x 和儲存 it 之間,未對 x 發出任何修改作業。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_node_map,則在載入 x 和載入 it 之間,未對 x 發出任何修改作業。

類別模板 unordered_node_set

boost::unordered_node_set — 一個基於節點的開放定址無序關聯容器,用於儲存唯一值。

boost::unordered_node_set 使用類似於 boost::unordered_flat_set 的開放定址佈局,但由於是基於節點的,因此它提供指標穩定性和節點處理功能。其效能介於 boost::unordered_setboost::unordered_flat_set 之間。

由於使用開放定址,boost::unordered_node_set 的介面在許多方面與 boost::unordered_set/std::unordered_set 的介面不同

  • begin() 不是常數時間。

  • 沒有用於儲存桶處理的 API(除了 bucket_count)。

  • 容器的最大負載因子由內部管理,使用者無法設定。

除此之外,boost::unordered_node_set 大多數情況下可以作為標準無序關聯容器的替代品。

概要

// #include <boost/unordered/unordered_node_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class unordered_node_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using init_type            = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using iterator             = implementation-defined;
    using const_iterator       = implementation-defined;

    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // construct/copy/destroy
    unordered_node_set();
    explicit unordered_node_set(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template<class InputIterator>
      unordered_node_set(InputIterator f, InputIterator l,
                         size_type n = implementation-defined,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_node_set(const unordered_node_set& other);
    unordered_node_set(unordered_node_set&& other);
    template<class InputIterator>
      unordered_node_set(InputIterator f, InputIterator l, const allocator_type& a);
    explicit unordered_node_set(const Allocator& a);
    unordered_node_set(const unordered_node_set& other, const Allocator& a);
    unordered_node_set(unordered_node_set&& other, const Allocator& a);
    unordered_node_set(concurrent_node_set<Key, Hash, Pred, Allocator>&& other);
    unordered_node_set(std::initializer_list<value_type> il,
                       size_type n = implementation-defined
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_node_set(size_type n, const allocator_type& a);
    unordered_node_set(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      unordered_node_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
    template<class InputIterator>
      unordered_node_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);
    unordered_node_set(std::initializer_list<value_type> il, const allocator_type& a);
    unordered_node_set(std::initializer_list<value_type> il, size_type n,
                       const allocator_type& a);
    unordered_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a);
    ~unordered_node_set();
    unordered_node_set& operator=(const unordered_node_set& other);
    unordered_node_set& operator=(unordered_node_set&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    unordered_node_set& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
    template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    std::pair<iterator, bool> insert(const value_type& obj);
    std::pair<iterator, bool> insert(value_type&& obj);
    template<class K> std::pair<iterator, bool> insert(K&& k);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template<class K> iterator insert(const_iterator hint, K&& k);
    template<class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type>);
    insert_return_type insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    convertible-to-iterator     erase(iterator position);
    convertible-to-iterator     erase(const_iterator position);
    size_type                   erase(const key_type& k);
    template<class K> size_type erase(K&& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_node_set& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    node_type extract(const_iterator position);
    node_type extract(const key_type& key);
    template<class K> node_type extract(K&& key);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_node_set<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_node_set<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    iterator         find(const key_type& k);
    const_iterator   find(const key_type& k) const;
    template<class K>
      iterator       find(const K& k);
    template<class K>
      const_iterator find(const K& k) const;
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;
    std::pair<iterator, iterator>               equal_range(const key_type& k);
    std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
    template<class K>
      std::pair<iterator, iterator>             equal_range(const K& k);
    template<class K>
      std::pair<const_iterator, const_iterator> equal_range(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    unordered_node_set(InputIterator, InputIterator, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_node_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    unordered_node_set(std::initializer_list<T>, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_node_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_node_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_node_set<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_node_set(InputIterator, InputIterator, Allocator)
      -> unordered_node_set<iter-value-type<InputIterator>,
                            boost::hash<iter-value-type<InputIterator>>,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_node_set(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_node_set<iter-value-type<InputIterator>, Hash,
                            std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    unordered_node_set(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    unordered_node_set(std::initializer_list<T>, Allocator)
      -> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_node_set(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_node_set<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
                    const unordered_node_set<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
              unordered_node_set<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename unordered_node_set<K, T, H, P, A>::size_type
       erase_if(unordered_node_set<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using unordered_node_set =
      boost::unordered_node_set<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可以從容器中消除

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。

容器的元素節點會保留在內部「儲存桶陣列」中。節點會插入由其元素雜湊碼決定的儲存桶中,但如果該儲存桶已被佔用 (發生「衝突」),則會使用原始位置附近的可用儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或者透過呼叫 rehash/reserve 增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor(),除非在實作決定允許更高負載的小尺寸情況下。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


組態巨集

BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集以啟用容器的統計計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。

可轉換為 const_iterator


typedef implementation-defined const_iterator;

值類型為 value_type 的常數迭代器。

迭代器類別至少是前向迭代器。


typedef implementation-defined node_type;

一個用於保存提取的容器元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class Iterator, class NodeType>
struct insert_return_type // name is exposition only
{
  Iterator position;
  bool     inserted;
  NodeType node;
};

其中 Iterator = iteratorNodeType = node_type


建構子

預設建構函式
unordered_node_set();

使用 hasher() 作為雜湊函數、key_equal() 作為鍵相等述詞和 allocator_type() 作為配置器,建構一個空的容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit unordered_node_set(size_type n,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  unordered_node_set(InputIterator f, InputIterator l,
                     size_type n = implementation-defined,
                     const hasher& hf = hasher(),
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
unordered_node_set(unordered_node_set const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的


移動建構函式
unordered_node_set(unordered_node_set&& other);

移動建構函式。other 的內部儲存桶陣列會直接轉移到新容器。雜湊函式、述詞和配置器會從 other 移動建構。如果 啟用統計資料,則會將內部統計資訊從 other 傳輸過來,並呼叫 other.reset_stats()


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  unordered_node_set(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit unordered_node_set(Allocator const& a);

建構一個空容器,使用分配器 a


具有分配器的複製建構函式
unordered_node_set(unordered_node_set const& other, Allocator const& a);

建構一個容器,複製 other 包含的元素、雜湊函數和述詞,但使用配置器 a


具備配置器的移動建構子
unordered_node_set(unordered_node_set&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素節點會直接轉移到新容器;否則,元素會從 other 的元素移動建構。雜湊函式和述詞會從 other 移動建構,而配置器則從 a 複製建構。如果 啟用統計資料,則當且僅當 a == other.get_allocator() 時,才會將內部統計資訊從 other 傳輸過來,並一律呼叫 other.reset_stats()


從 concurrent_node_set 移動建構函式
unordered_node_set(concurrent_node_set<Key, Hash, Pred, Allocator>&& other);

concurrent_node_set 移動建構。other 的內部儲存桶陣列會直接轉移到新容器。雜湊函式、述詞和配置器會從 other 移動建構。如果 啟用統計資料,則會將內部統計資訊從 other 傳輸過來,並呼叫 other.reset_stats()

複雜度

常數時間。

並行性

other 上鎖定。


初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il,
              size_type n = implementation-defined
              const hasher& hf = hasher(),
              const key_equal& eql = key_equal(),
              const allocator_type& a = allocator_type());

使用 hf 作為雜湊函數、eql 作為鍵相等述詞和 a,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
unordered_node_set(size_type n, allocator_type const& a);

使用 hf 作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
unordered_node_set(size_type n, hasher const& hf, allocator_type const& a);

使用 hf 作為雜湊函數、預設的鍵相等述詞和 a 作為配置器,建構一個至少有 n 個儲存桶的空容器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  unordered_node_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

使用 a 作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      unordered_node_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 [f, l) 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

使用 a 和預設的雜湊函數和鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                   const allocator_type& a);

使用 hf 作為雜湊函數、a 作為配置器,以及預設的鍵相等述詞,建構一個至少有 n 個儲存桶的空容器,並將 il 中的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~unordered_node_set();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
unordered_node_set& operator=(unordered_node_set const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入


移動賦值
unordered_node_set& operator=(unordered_node_set&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動指派運算子。銷毀先前存在的元素,從 other 交換雜湊函式和述詞,如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則會從 other 移動指派配置器。如果此時配置器等於 other.get_allocator(),則 other 的內部儲存桶陣列會直接轉移到新容器;否則,會插入 other 元素的移動建構副本。如果 啟用統計資料,則當且僅當最終配置器等於 other.get_allocator() 時,才會將內部統計資訊從 other 傳輸過來,並一律呼叫 other.reset_stats()


初始化列表賦值
unordered_node_set& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

迭代器

begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回

一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


end
iterator end() noexcept;
const_iterator end() const noexcept;
傳回

一個指向容器超出尾端值的迭代器。


cbegin
const_iterator cbegin() const noexcept;
傳回

一個 const_iterator,指向容器第一個元素,如果容器是空的,則傳回容器的超出尾端值。

複雜度

O(bucket_count())


cend
const_iterator cend() const noexcept;
傳回

一個 const_iterator,指向容器的超出尾端值。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

std::distance(begin(), end())


max_size
size_type max_size() const noexcept;
傳回

最大可能容器的 size()


修改器

emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


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

如果容器中沒有具有相等鍵值的元素,則使用引數 args 建構的物件插入到容器中。

position 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可從 args 建構。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


複製插入
std::pair<iterator, bool> insert(const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


移動插入
std::pair<iterator, bool> insert(value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);

如果容器中沒有具有相等鍵值的元素,則將 obj 插入容器中。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果發生插入,則傳回類型的 bool 元件為 true

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


具有提示的透明插入
template<class K> std::pair<iterator, bool> insert(const_iterator hint, K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

hint 是建議插入元素的位置。此實作會忽略它。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果發生插入,則傳回類型的布林值元件為 true。

如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 且 iteratorconst_iterator 都不能從 K 隱式轉換時,此多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以實現異質查詢,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 可以從 *first 就地建構到容器中。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


插入初始化列表
void insert(std::initializer_list<value_type>);

將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。

需求

value_type 是可複製插入 (CopyInsertable) 到容器中的。

拋出

當插入單一元素時,如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。


插入節點
insert_return_type insert(node_type&& nh);

如果 nh 不為空,則當且僅當容器中沒有與 nh.value() 等效鍵的元素時,才將關聯的元素插入容器。當函式傳回時,nh 為空。

傳回

一個由 positioninsertednode 建構而成的 insert_return_type 物件

  • 如果 nh 是空的,則 insertedfalsepositionend(),且 node 為空。

  • 否則,如果插入成功,則 inserted 為 true,position 指向插入的元素,且 node 為空。

  • 如果插入失敗,則 inserted 為 false,node 具有 nh 的先前值,且 position 指向具有與 nh.value() 等效鍵的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


使用提示插入節點
iterator insert(const_iterator hint, node_type&& nh);

如果 nh 不為空,則當且僅當容器中沒有與 nh.value() 等效鍵的元素時,才將關聯的元素插入容器。如果插入成功,nh 會變為空,否則不會變更。

hint 是建議插入元素的位置。此實作會忽略它。

傳回

如果 nh 為空,則傳回的迭代器為 end()。如果插入成功,則迭代器指向新插入的元素;否則,它指向具有等效鍵的元素。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);

刪除 position 所指向的元素。

傳回

一個不透明物件,可以隱式轉換為刪除前緊接在 position 之後的 iteratorconst_iterator

拋出

無。

注意

傳回的不透明物件只能被捨棄或立即轉換為 iteratorconst_iterator


依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);

刪除所有鍵與 k 等價的元素。

傳回

已刪除的元素數量。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef,並且 iteratorconst_iterator 都不能從 K 隱式轉換時,template<class K> 多載才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


刪除範圍
iterator erase(const_iterator first, const_iterator last);

刪除從 firstlast 範圍內的元素。

傳回

刪除的元素之後的迭代器,即 last

拋出

在此實作中無任何作用(不會呼叫 hasherkey_equal 物件)。


交換 (swap)
void swap(unordered_node_set& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將容器的內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


依位置提取
node_type extract(const_iterator position);

提取 position 所指向的元素。

傳回

一個包含提取元素的 node_type 物件。

拋出

無。


透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

提取具有與 k 等效鍵的元素(如果存在)。

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


清除 (clear)
void clear() noexcept;

刪除容器中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()


合併 (merge)
template<class H2, class P2>
  void merge(unordered_node_set<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  void merge(unordered_node_set<Key, T, H2, P2, Allocator>&& source);

source 中所有鍵未出現在 *this 中的元素節點傳輸過來。

需求

this->get_allocator() == source.get_allocator().

注意

使傳輸元素的迭代器失效。如果 *this 的結果大小大於其原始最大負載,則使與 *this 關聯的所有迭代器失效。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

容器的配置器。


hash_function
hasher hash_function() const;
傳回

容器的雜湊函數。


key_eq
key_equal key_eq() const;
傳回

容器的鍵相等述詞。


查找

尋找 (find)
iterator         find(const key_type& k);
const_iterator   find(const key_type& k) const;
template<class K>
  iterator       find(const K& k);
傳回

指向鍵值與 k 相等的元素的迭代器,如果不存在此類元素,則返回 end()

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等價鍵的元素數量。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指出容器中是否存在具有與 key 相等鍵的元素

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


相等範圍 (equal_range)
std::pair<iterator, iterator>               equal_range(const key_type& k);
std::pair<const_iterator, const_iterator>   equal_range(const key_type& k) const;
template<class K>
  std::pair<iterator, iterator>             equal_range(const K& k);
template<class K>
  std::pair<const_iterator, const_iterator> equal_range(const K& k) const;
傳回

包含所有具有與 k 等價鍵的元素的範圍。如果容器不包含任何此類元素,則回傳 std::make_pair(b.end(), b.end())

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回容器的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_set 相容。


max_load
size_type max_load() const noexcept;
傳回

容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。

注意

建構、重新雜湊或清除後,容器的最大負載至少為 max_load_factor() * bucket_count()。在高負載情況下刪除元素時,此數值可能會減少。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,並且負載因子小於或等於最大負載因子。在適用的情況下,這將會增加或縮減與容器相關聯的 bucket_count()

size() == 0 時,rehash(0) 將會釋放底層的儲存桶陣列。如果提供的配置器使用花俏指標,則後續會執行預設配置。

使迭代器失效並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函數可用於增加或縮減容器中的儲存桶數量。

使迭代器失效並變更元素的順序。

拋出

如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。


統計

get_stats
stats get_stats() const;
傳回

容器目前為止執行的插入和查找操作的統計描述。

注意

僅當 統計資料計算 啟用時才可用。


reset_stats
void reset_stats() noexcept;
作用

將容器保留的內部統計資料設為零。

注意

僅當 統計資料計算 啟用時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_node_set<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 true

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
                  const unordered_node_set<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵且值相等的元素(使用 operator== 來比較值類型),則回傳 false

注意

如果兩個容器不具有等價的相等述詞,則行為未定義。

交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(unordered_node_set<Key, T, Hash, Pred, Alloc>& x,
            unordered_node_set<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

交換 xy 的內容。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。

作用

x.swap(y)

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。


erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename unordered_node_set<K, T, H, P, A>::size_type
    erase_if(unordered_node_set<K, T, H, P, A>& c, Predicate pred);

走訪容器 c 並移除提供的述詞回傳 true 的所有元素。

傳回

已刪除的元素數量。

注意

等同於

auto original_size = c.size();
for (auto i = c.begin(), last = c.end(); i != last; ) {
  if (pred(*i)) {
    i = c.erase(i);
  } else {
    ++i;
  }
}
return original_size - c.size();

序列化

可以透過此程式庫提供的 API,使用 Boost.Serialization 封存/擷取 unordered_node_set。支援常規和 XML 封存。

將 unordered_node_set 儲存到封存

unordered_node_set x 的所有元素儲存到封存 (XML 封存) ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。


從封存載入 unordered_node_set

刪除 unordered_node_set x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入儲存在 ar 讀取儲存區的原始 unordered_node_set other 元素的還原副本。

需求

value_type可移動插入 (MoveInsertable) 的。x.key_equal() 的功能與 other.key_equal() 等效。


將迭代器/const_iterator 儲存到封存檔

iterator (const_iterator) it 的位置資訊儲存到封存檔 (XML 封存檔) arit 可以是 end() 迭代器。

需求

it 所指向的 unordered_node_set x 先前已儲存至 ar,且在儲存 x 和儲存 it 之間,未對 x 發出任何修改作業。


從封存檔載入迭代器/const_iterator

使 iterator (const_iterator) it 指向從封存檔 (XML 封存檔) ar 讀取的儲存空間中所儲存的原始 iterator (const_iterator) 的還原位置。

需求

如果 xit 所指向的 unordered_node_set,則在載入 x 和載入 it 之間,未對 x 發出任何修改作業。

類別模板 concurrent_flat_map

boost::concurrent_flat_map — 一個將唯一鍵與另一個值相關聯,並允許並行元素插入、刪除、查閱和存取,而無需外部同步機制的雜湊表。

即使它充當容器,boost::concurrent_flat_map 並未對標準 C++ Container 概念建模。特別是,不提供迭代器和相關作業 (beginend 等)。元素存取和修改是透過使用者提供的存取函式完成的,這些函式會傳遞給 concurrent_flat_map 作業,並在內部以受控制的方式執行。這種基於存取的 API 允許低競爭的並行使用情況。

boost::concurrent_flat_map 的內部資料結構類似於 boost::unordered_flat_map 的資料結構。由於使用開放定址技術,value_type 必須是可移動建構的,且在重新雜湊時不會保持指標穩定性。

概要

// #include <boost/unordered/concurrent_flat_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class concurrent_flat_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using init_type            = std::pair<
                                   typename std::remove_const<Key>::type,
                                   typename std::remove_const<T>::type
                                 >;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using stats                = stats-type; // if statistics are enabled

    // constants
    static constexpr size_type bulk_visit_size = implementation-defined;

    // construct/copy/destroy
    concurrent_flat_map();
    explicit concurrent_flat_map(size_type n,
                                 const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    template<class InputIterator>
      concurrent_flat_map(InputIterator f, InputIterator l,
                          size_type n = implementation-defined,
                          const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
    concurrent_flat_map(const concurrent_flat_map& other);
    concurrent_flat_map(concurrent_flat_map&& other);
    template<class InputIterator>
      concurrent_flat_map(InputIterator f, InputIterator l,const allocator_type& a);
    explicit concurrent_flat_map(const Allocator& a);
    concurrent_flat_map(const concurrent_flat_map& other, const Allocator& a);
    concurrent_flat_map(concurrent_flat_map&& other, const Allocator& a);
    concurrent_flat_map(unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other);
    concurrent_flat_map(std::initializer_list<value_type> il,
                        size_type n = implementation-defined
                        const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
    concurrent_flat_map(size_type n, const allocator_type& a);
    concurrent_flat_map(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      concurrent_flat_map(InputIterator f, InputIterator l, size_type n,
                          const allocator_type& a);
    template<class InputIterator>
      concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);
    concurrent_flat_map(std::initializer_list<value_type> il, const allocator_type& a);
    concurrent_flat_map(std::initializer_list<value_type> il, size_type n,
                        const allocator_type& a);
    concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                        const allocator_type& a);
    ~concurrent_flat_map();
    concurrent_flat_map& operator=(const concurrent_flat_map& other);
    concurrent_flat_map& operator=(concurrent_flat_map&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    concurrent_flat_map& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;


    // visitation
    template<class F> size_t visit(const key_type& k, F f);
    template<class F> size_t visit(const key_type& k, F f) const;
    template<class F> size_t cvisit(const key_type& k, F f) const;
    template<class K, class F> size_t visit(const K& k, F f);
    template<class K, class F> size_t visit(const K& k, F f) const;
    template<class K, class F> size_t cvisit(const K& k, F f) const;

    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f);
    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f) const;
    template<class FwdIterator, class F>
      size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

    template<class F> size_t visit_all(F f);
    template<class F> size_t visit_all(F f) const;
    template<class F> size_t cvisit_all(F f) const;
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      void cvisit_all(ExecutionPolicy&& policy, F f) const;

    template<class F> bool visit_while(F f);
    template<class F> bool visit_while(F f) const;
    template<class F> bool cvisit_while(F f) const;
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      bool cvisit_while(ExecutionPolicy&& policy, F f) const;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> bool emplace(Args&&... args);
    bool insert(const value_type& obj);
    bool insert(const init_type& obj);
    bool insert(value_type&& obj);
    bool insert(init_type&& obj);
    template<class InputIterator> size_type insert(InputIterator first, InputIterator last);
    size_type insert(std::initializer_list<value_type> il);

    template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
    template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);
    template<class F> bool insert_or_visit(const value_type& obj, F f);
    template<class F> bool insert_or_cvisit(const value_type& obj, F f);
    template<class F> bool insert_or_visit(const init_type& obj, F f);
    template<class F> bool insert_or_cvisit(const init_type& obj, F f);
    template<class F> bool insert_or_visit(value_type&& obj, F f);
    template<class F> bool insert_or_cvisit(value_type&& obj, F f);
    template<class F> bool insert_or_visit(init_type&& obj, F f);
    template<class F> bool insert_or_cvisit(init_type&& obj, F f);
    template<class InputIterator,class F>
      size_type insert_or_visit(InputIterator first, InputIterator last, F f);
    template<class InputIterator,class F>
      size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
    template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
    template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

    template<class... Args, class F1, class F2>
      bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);
    template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(const init_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const init_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(init_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

    template<class... Args> bool try_emplace(const key_type& k, Args&&... args);
    template<class... Args> bool try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args> bool try_emplace(K&& k, Args&&... args);

    template<class... Args, class F>
      bool try_emplace_or_visit(const key_type& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_cvisit(const key_type& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_visit(key_type&& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_cvisit(key_type&& k, Args&&... args, F&& f);
    template<class K, class... Args, class F>
      bool try_emplace_or_visit(K&& k, Args&&... args, F&& f);
    template<class K, class... Args, class F>
      bool try_emplace_or_cvisit(K&& k, Args&&... args, F&& f);

    template<class... Args, class F1, class F2>
      bool try_emplace_and_visit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_visit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class K, class... Args, class F1, class F2>
      bool try_emplace_and_visit(K&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class K, class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(K&& k, Args&&... args, F1&& f1, F2&& f2);

    template<class M> bool insert_or_assign(const key_type& k, M&& obj);
    template<class M> bool insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M> bool insert_or_assign(K&& k, M&& obj);

    size_type erase(const key_type& k);
    template<class K> size_type erase(const K& k);

    template<class F> size_type erase_if(const key_type& k, F f);
    template<class K, class F> size_type erase_if(const K& k, F f);
    template<class F> size_type erase_if(F f);
    template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

    void      swap(concurrent_flat_map& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    void      clear() noexcept;

    template<class H2, class P2>
      size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    concurrent_flat_map(InputIterator, InputIterator, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                             Pred, Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    concurrent_flat_map(std::initializer_list<std::pair<Key, T>>,
                        typename see below::size_type = see below, Hash = Hash(),
                        Pred = Pred(), Allocator = Allocator())
      -> concurrent_flat_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_flat_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> concurrent_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                             boost::hash<iter-key-type<InputIterator>>,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_flat_map(InputIterator, InputIterator, Allocator)
      -> concurrent_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                             boost::hash<iter-key-type<InputIterator>>,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    concurrent_flat_map(InputIterator, InputIterator, typename see below::size_type, Hash,
                        Allocator)
      -> concurrent_flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    concurrent_flat_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                        Allocator)
      -> concurrent_flat_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    concurrent_flat_map(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> concurrent_flat_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    concurrent_flat_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                        Hash, Allocator)
      -> concurrent_flat_map<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
                    const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
                    const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
              concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename concurrent_flat_map<K, T, H, P, A>::size_type
       erase_if(concurrent_flat_map<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using concurrent_flat_map =
      boost::concurrent_flat_map<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

KeyT 必須是 可移動建構的。必須可從任何可轉換為它的 std::pair 物件,將 std::pair<const Key, T> 就地建構到資料表中,而且也必須可以從資料表中 消除

T

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

配置器的值類型與資料表的值類型相同。支援使用 花俏指標的配置器。

資料表的元素會保留在內部儲存桶陣列中。元素會插入到由其雜湊碼決定的儲存桶中,但如果儲存桶已佔用 (衝突),則會使用原始位置附近的可用儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或透過呼叫 rehash/reserve 來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor(),除了實作可能會決定允許更高載入的小型大小之外。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


並行需求和保證

需要在相同的 HashPred 常數執行個體上並行呼叫 operator(),而不會引入資料競爭。對於 AllocAllocator 或從 Allocator 重新繫結的任何配置器類型,需要在 Alloc 的相同執行個體 al 上並行呼叫以下作業,而不會引入資料競爭

  • Alloc 重新繫結的配置器 al 的複製建構

  • std::allocator_traits<Alloc>::allocate

  • std::allocator_traits<Alloc>::deallocate

  • std::allocator_traits<Alloc>::construct

  • std::allocator_traits<Alloc>::destroy

一般而言,如果 HashPredAllocator 這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。

除了銷毀操作外,在同一個 concurrent_flat_map 實例上併發呼叫任何操作都不會引入資料競爭 — 也就是說,它們是執行緒安全的。

如果某個操作 op 被明確指定為阻塞於 x,其中 xboost::concurrent_flat_map 的一個實例,則先前對 x 的阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_flat_map 的阻塞操作會依序執行。

如果某個操作僅在發出內部重新雜湊時才阻塞於 x,則稱該操作阻塞於 x 的重新雜湊

當由 boost::concurrent_flat_map 內部執行時,使用者提供的訪問函數對傳遞的元素執行以下操作不會引入資料競爭:

  • 對元素的讀取存取。

  • 對元素的不可變修改。

  • 對元素的可變修改。

    • 在接受兩個訪問函數的容器函數中,總是針對第一個函數。

    • 在名稱不包含 cvisit 的非常數容器函數中,針對最後一個(或唯一)的訪問函數。

任何插入或修改元素 eboost::concurrent_flat_map 操作都會與對 e 的內部訪問函數呼叫同步。

boost::concurrent_flat_map x 執行的訪問函數不允許呼叫 x 上的任何操作;只有當對 y 的併發未完成操作不直接或間接地存取 x 時,才允許呼叫不同 boost::concurrent_flat_map 實例 y 上的操作。


組態巨集

BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK

在偵錯建置中(更精確地說,當 BOOST_ASSERT_IS_VOID 未定義時),會偵測到容器重入(從訪問 m 元素的函數中非法呼叫 m 上的操作),並透過 BOOST_ASSERT_MSG 發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。


BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集,以啟用表格的統計資訊計算。請注意,此選項會降低許多操作的整體效能。


常數

static constexpr size_type bulk_visit_size;

批量訪問操作中內部使用的區塊大小。

建構子

預設建構函式
concurrent_flat_map();

使用 hasher() 作為雜湊函數,key_equal() 作為鍵相等謂詞,以及 allocator_type() 作為分配器,建構一個空表格。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit concurrent_flat_map(size_type n,
                             const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  concurrent_flat_map(InputIterator f, InputIterator l,
                      size_type n = implementation-defined,
                      const hasher& hf = hasher(),
                      const key_equal& eql = key_equal(),
                      const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
concurrent_flat_map(concurrent_flat_map const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的

並行性

other 上鎖定。


移動建構函式
concurrent_flat_map(concurrent_flat_map&& other);

移動建構函式。other 的內部儲存桶陣列直接轉移到新表格。雜湊函數、謂詞和分配器從 other 移動建構。如果 已啟用統計資訊,則從 other 轉移內部統計資訊並呼叫 other.reset_stats()

並行性

other 上鎖定。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  concurrent_flat_map(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit concurrent_flat_map(Allocator const& a);

使用分配器 a,建構一個空表格。


具有分配器的複製建構函式
concurrent_flat_map(concurrent_flat_map const& other, Allocator const& a);

建構一個表格,複製 other 包含的元素、雜湊函數和謂詞,但使用分配器 a

並行性

other 上鎖定。


具備配置器的移動建構子
concurrent_flat_map(concurrent_flat_map&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接轉移到新表格;否則,元素會從 other 的元素移動建構。雜湊函數和謂詞從 other 移動建構,並且分配器從 a 複製建構。如果 已啟用統計資訊,則只有當 a == other.get_allocator() 時,才會從 other 轉移內部統計資訊,並且總是呼叫 other.reset_stats()

並行性

other 上鎖定。


從 unordered_flat_map 移動建構函式
concurrent_flat_map(unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other);

unordered_flat_map 移動建構。other 的內部儲存桶陣列直接轉移到新容器。雜湊函數、謂詞和分配器從 other 移動建構。如果 已啟用統計資訊,則從 other 轉移內部統計資訊並呼叫 other.reset_stats()

複雜度

O(bucket_count())


初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il,
                    size_type n = implementation-defined
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a,並將來自 il 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
concurrent_flat_map(size_type n, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
concurrent_flat_map(size_type n, hasher const& hf, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 以及預設雜湊函數和鍵相等謂詞,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                    const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 il 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~concurrent_flat_map();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
concurrent_flat_map& operator=(concurrent_flat_map const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入

並行性

阻塞於 *thisother


移動賦值
concurrent_flat_map& operator=(concurrent_flat_map&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動賦值運算子。銷毀先前存在的元素,交換來自 other 的雜湊函數和謂詞,如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則從 other 移動賦值分配器。如果此時分配器等於 other.get_allocator(),則 other 的內部儲存桶陣列會直接轉移到 *this;否則,插入 other 元素的移動建構副本。如果 已啟用統計資訊,則只有當最終分配器等於 other.get_allocator() 時,才會從 other 轉移內部統計資訊,並且總是呼叫 other.reset_stats()

並行性

阻塞於 *thisother


初始化列表賦值
concurrent_flat_map& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

並行性

阻塞於 *this


訪問

[c]visit
template<class F> size_t visit(const key_type& k, F f);
template<class F> size_t visit(const key_type& k, F f) const;
template<class F> size_t cvisit(const key_type& k, F f) const;
template<class K, class F> size_t visit(const K& k, F f);
template<class K, class F> size_t visit(const K& k, F f) const;
template<class K, class F> size_t cvisit(const K& k, F f) const;

如果存在一個與 k 等效的鍵的元素 x,則使用對 x 的引用呼叫 f。只有當 *this 是常數時,此引用才是常數。

傳回

訪問的元素數 (0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。


批量訪問
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
  size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

對於範圍 [first, last) 中的每個元素 k,如果容器中存在一個與 k 等效的鍵的元素 x,則使用對 x 的引用呼叫 f。只有當 *this 是常數時,此引用才是常數。

雖然在功能上等效於個別呼叫每個鍵的 [c]visit,但由於內部簡化最佳化,批量訪問通常會更快。建議 std::distance(first,last) 至少為 bulk_visit_size 才能享受效能提升:超出此大小後,效能預期不會進一步提高。

需求

FwdIterator 是一個 LegacyForwardIterator (C++11 至 C++17),或滿足 std::forward_iterator (C++20 及更高版本)。對於 K = std::iterator_traits<FwdIterator>::value_typeK 要麼是 key_type,否則 Hash::is_transparentPred::is_transparent 是有效的成員 typedef。在後一種情況下,程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。

傳回

訪問的元素數。


[c]visit_all
template<class F> size_t visit_all(F f);
template<class F> size_t visit_all(F f) const;
template<class F> size_t cvisit_all(F f) const;

使用對表格中每個元素的引用,依序呼叫 f。只有當 *this 是常數時,此引用才是常數。

傳回

訪問的元素數。


平行 [c]visit_all
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> void cvisit_all(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的引用,呼叫 f。只有當 *this 是常數時,此引用才是常數。執行會根據指定的執行策略語意進行平行處理。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。


[c]visit_while
template<class F> bool visit_while(F f);
template<class F> bool visit_while(F f) const;
template<class F> bool cvisit_while(F f) const;

使用對表格中每個元素的引用,依序呼叫 f,直到 f 傳回 false 或所有元素都被訪問完為止。只有當 *this 是常數時,對元素的引用才是常數。

傳回

如果 f 曾經傳回 false,則為 false


平行 [c]visit_while
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> bool cvisit_while(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的引用,呼叫 f,直到 f 傳回 false 或所有元素都被訪問完為止。只有當 *this 是常數時,對元素的引用才是常數。執行會根據指定的執行策略語意進行平行處理。

傳回

如果 f 曾經傳回 false,則為 false

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。

平行化表示執行不一定在 f 傳回 false 後立即完成,因此,f 可能會使用傳回值也為 false 的其他元素呼叫。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

表格中的元素數。

注意

在存在併發插入操作的情況下,傳回的值可能無法準確反映執行後表格的實際大小。


max_size
size_type max_size() const noexcept;
傳回

最大可能表格的 size()


修改器

emplace
template<class... Args> bool emplace(Args&&... args);

只有當表格中不存在具有等效鍵的元素時,才將使用引數 args 建構的物件插入表格中。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素,僅使用 k 引數進行檢查。


複製插入
bool insert(const value_type& obj);
bool insert(const init_type& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


移動插入
bool insert(value_type&& obj);
bool insert(init_type&& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


插入迭代器範圍
template<class InputIterator> size_type insert(InputIterator first, InputIterator last);

等同於

  while(first != last) this->emplace(*first++);
傳回

插入的元素數量。


插入初始化列表
size_type insert(std::initializer_list<value_type> il);

等同於

  this->insert(il.begin(), il.end());
傳回

插入的元素數量。


emplace_or_[c]visit
template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);

如果表中沒有具有等效鍵的元素,則將使用參數 args 建構的物件插入表中。否則,會使用對等效元素的參考來調用 f;當使用 emplace_or_cvisit 時,此參考為 const。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f


複製 insert_or_[c]visit
template<class F> bool insert_or_visit(const value_type& obj, F f);
template<class F> bool insert_or_cvisit(const value_type& obj, F f);
template<class F> bool insert_or_visit(const init_type& obj, F f);
template<class F> bool insert_or_cvisit(const init_type& obj, F f);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

insert_or_[c]visit(obj, f) 形式的調用中,只有當 std::remove_cv<std::remove_reference<decltype(obj)>::type>::typevalue_type 時,接受 const value_type& 參數的多載才會參與多載解析。


移動 insert_or_[c]visit
template<class F> bool insert_or_visit(value_type&& obj, F f);
template<class F> bool insert_or_cvisit(value_type&& obj, F f);
template<class F> bool insert_or_visit(init_type&& obj, F f);
template<class F> bool insert_or_cvisit(init_type&& obj, F f);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

insert_or_[c]visit(obj, f) 形式的調用中,只有當 std::remove_reference<decltype(obj)>::typevalue_type 時,接受 value_type&& 參數的多載才會參與多載解析。


插入迭代器範圍或訪問
template<class InputIterator,class F>
    size_type insert_or_visit(InputIterator first, InputIterator last, F f);
template<class InputIterator,class F>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);

等同於

  while(first != last) this->emplace_or_[c]visit(*first++, f);
傳回

插入的元素數量。


插入初始化列表或訪問
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

等同於

  this->insert_or_[c]visit(il.begin(), il.end(), std::ref(f));
傳回

插入的元素數量。


emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);

如果表中沒有具有等效鍵的元素,則將使用參數 args 建構的物件插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 emplace_and_cvisit 時,此參考為 const。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f1f2


複製 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_visit(const init_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const init_type& obj, F1 f1, F2 f2);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

insert_and_[c]visit(obj, f1, f2) 形式的調用中,只有當 std::remove_cv<std::remove_reference<decltype(obj)>::type>::typevalue_type 時,接受 const value_type& 參數的多載才會參與多載解析。


移動 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_visit(init_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

insert_and_[c]visit(obj, f1, f2) 形式的調用中,只有當 std::remove_reference<decltype(obj)>::typevalue_type 時,接受 value_type&& 參數的多載才會參與多載解析。


插入迭代器範圍和訪問
template<class InputIterator, class F1, class F2>
    size_type insert_or_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
template<class InputIterator, class F1, class F2>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);

等同於

  while(first != last) this->emplace_and_[c]visit(*first++, f1, f2);
傳回

插入的元素數量。


插入初始化列表和訪問
template<class F1, class F2>
  size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
template<class F1, class F2>
  size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

等同於

  this->insert_and_[c]visit(il.begin(), il.end(), std::ref(f1), std::ref(f2));
傳回

插入的元素數量。


try_emplace
template<class... Args> bool try_emplace(const key_type& k, Args&&... args);
template<class... Args> bool try_emplace(key_type&& k, Args&&... args);
template<class K, class... Args> bool try_emplace(K&& k, Args&&... args);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此函式類似於 emplace,區別在於如果存在具有等效鍵的元素,則不會建構任何 value_type;否則,建構形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace 不同,後者只是將所有參數轉發到 value_type 的建構函式。

如果發出重新雜湊,則會使指向元素的指標和參考失效。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


try_emplace_or_[c]visit
template<class... Args, class F>
  bool try_emplace_or_visit(const key_type& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_cvisit(const key_type& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_visit(key_type&& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_cvisit(key_type&& k, Args&&... args, F&& f);
template<class K, class... Args, class F>
  bool try_emplace_or_visit(K&& k, Args&&... args, F&& f);
template<class K, class... Args, class F>
  bool try_emplace_or_cvisit(K&& k, Args&&... args, F&& f);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果存在具有等效鍵的元素,則不會建構任何 value_type;否則,建構形式為

// first four overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// last two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


try_emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool try_emplace_and_visit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_visit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
template<class K, class... Args, class F1, class F2>
  bool try_emplace_and_visit(K&& k, Args&&... args, F1&& f1, F2&& f2);
template<class K, class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(K&& k, Args&&... args, F1&& f1, F2&& f2);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果存在具有等效鍵的元素,則不會建構任何 value_type;否則,建構形式為

// first four overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// last two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f1f2

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args, class F1, class F2> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


insert_or_assign
template<class M> bool insert_or_assign(const key_type& k, M&& obj);
template<class M> bool insert_or_assign(key_type&& k, M&& obj);
template<class K, class M> bool insert_or_assign(K&& k, M&& obj);

將新元素插入表中,或透過賦值給包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有此類元素,則會將其新增至表格中,如下所示

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))
傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);

如果存在具有與 k 等效鍵的元素,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


依鍵刪除_if
template<class F> size_type erase_if(const key_type& k, F f);
template<class K, class F> size_type erase_if(const K& k, F f);

如果存在具有與 k 等效鍵的元素 x,且 f(x)true,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

只有當 hasherkey_equalf 擲回例外時,才會擲回例外。

注意

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>false 時,template<class K, class F> 多載才會參與多載解析。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


erase_if
template<class F> size_type erase_if(F f);

使用表格中每個元素的參考來連續調用 f,並刪除 f 返回 true 的元素。

傳回

已刪除的元素數量。

拋出

只有當 f 擲回例外時,才會擲回例外。


平行刪除_if
template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

使用表格中每個元素的參考來調用 f,並刪除 f 返回 true 的元素。根據指定的執行原則語意來平行處理執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,此多載才會參與多載解析。

不允許未排序的執行策略。


交換 (swap)
void swap(concurrent_flat_map& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將表格內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。

並行性

阻塞於 *thisother


清除 (clear)
void clear() noexcept;

刪除表格中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()

並行性

阻塞於 *this


合併 (merge)
template<class H2, class P2>
  size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。

傳回

插入的元素數量。

並行性

*thissource 上封鎖。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

表格的配置器。


hash_function
hasher hash_function() const;
傳回

表格的雜湊函式。


key_eq
key_equal key_eq() const;
傳回

表格的鍵相等謂詞。


Map 操作

計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等效鍵的元素數量(0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指示表格中是否存在鍵等於 k 的元素。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回表格的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_map 相容。


max_load
size_type max_load() const noexcept;
傳回

在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。

注意

建構、重新雜湊或清除後,表格的最大負載至少為 max_load_factor() * bucket_count()。在高負載條件下刪除時,此數目可能會減少。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,且負載因子小於或等於最大負載因子。在適用的情況下,這會擴大或縮小與表格相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

會使指向元素的指標和參考失效,並變更元素的順序。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函式可用於擴大或縮小表格中的儲存桶數目。

會使指向元素的指標和參考失效,並變更元素的順序。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


統計

get_stats
stats get_stats() const;
傳回

到目前為止表格執行的插入和查閱操作的統計說明。

注意

只有在 啟用 統計計算 時才可用。


reset_stats
void reset_stats() noexcept;
作用

將表格保留的內部統計資料設定為零。

注意

只有在 啟用 統計計算 時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_­type 參數類型指的是推導指南推導的表格類型的 size_­type 成員類型。其預設值與選取的建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
                  const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 true

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
                  const concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 false

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
            concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

等同於

x.swap(y);

erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename concurrent_flat_map<K, T, H, P, A>::size_type
    erase_if(concurrent_flat_map<K, T, H, P, A>& c, Predicate pred);

等同於

c.erase_if(pred);

序列化

concurrent_flat_map 可使用此程式庫提供的 API,透過 Boost.Serialization 來歸檔/擷取。支援常規和 XML 歸檔。

將 concurrent_flat_map 儲存到歸檔

concurrent_flat_map x 的所有元素儲存到歸檔(XML 歸檔)ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。

並行性

x 上封鎖。


從歸檔載入 concurrent_flat_map

刪除 concurrent_flat_map x 的所有預先存在的元素,並從歸檔(XML 歸檔)ar 插入儲存到 ar 讀取的儲存中的原始 concurrent_flat_map other 的元素的還原副本。

需求

x.key_equal() 在功能上等同於 other.key_equal()

並行性

x 上封鎖。

類別模板 concurrent_flat_set

boost::concurrent_flat_set — 一個雜湊表,儲存唯一值,並允許並行插入、刪除、查找和存取元素,而無需外部同步機制。

即使它作為一個容器,boost::concurrent_flat_set 並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作(beginend 等)。元素存取是透過使用者提供的訪問函式完成,這些函式傳遞給 concurrent_flat_set 操作,在內部以受控的方式執行。這種基於訪問的 API 允許低爭用的並行使用場景。

boost::concurrent_flat_set 的內部資料結構與 boost::unordered_flat_set 類似。由於它使用開放定址技術,value_type 必須是可移動建構的,並且在重新雜湊時不會保持指標穩定性。

概要

// #include <boost/unordered/concurrent_flat_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class concurrent_flat_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using init_type            = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using stats                = stats-type; // if statistics are enabled

    // constants
    static constexpr size_type bulk_visit_size = implementation-defined;

    // construct/copy/destroy
    concurrent_flat_set();
    explicit concurrent_flat_set(size_type n,
                                 const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    template<class InputIterator>
      concurrent_flat_set(InputIterator f, InputIterator l,
                          size_type n = implementation-defined,
                          const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
    concurrent_flat_set(const concurrent_flat_set& other);
    concurrent_flat_set(concurrent_flat_set&& other);
    template<class InputIterator>
      concurrent_flat_set(InputIterator f, InputIterator l,const allocator_type& a);
    explicit concurrent_flat_set(const Allocator& a);
    concurrent_flat_set(const concurrent_flat_set& other, const Allocator& a);
    concurrent_flat_set(concurrent_flat_set&& other, const Allocator& a);
    concurrent_flat_set(unordered_flat_set<Key, Hash, Pred, Allocator>&& other);
    concurrent_flat_set(std::initializer_list<value_type> il,
                        size_type n = implementation-defined
                        const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
    concurrent_flat_set(size_type n, const allocator_type& a);
    concurrent_flat_set(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      concurrent_flat_set(InputIterator f, InputIterator l, size_type n,
                          const allocator_type& a);
    template<class InputIterator>
      concurrent_flat_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);
    concurrent_flat_set(std::initializer_list<value_type> il, const allocator_type& a);
    concurrent_flat_set(std::initializer_list<value_type> il, size_type n,
                        const allocator_type& a);
    concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                        const allocator_type& a);
    ~concurrent_flat_set();
    concurrent_flat_set& operator=(const concurrent_flat_set& other);
    concurrent_flat_set& operator=(concurrent_flat_set&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
              boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value);
    concurrent_flat_set& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;


    // visitation
    template<class F> size_t visit(const key_type& k, F f);
    template<class F> size_t visit(const key_type& k, F f) const;
    template<class F> size_t cvisit(const key_type& k, F f) const;
    template<class K, class F> size_t visit(const K& k, F f);
    template<class K, class F> size_t visit(const K& k, F f) const;
    template<class K, class F> size_t cvisit(const K& k, F f) const;

    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f);
    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f) const;
    template<class FwdIterator, class F>
      size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

    template<class F> size_t visit_all(F f);
    template<class F> size_t visit_all(F f) const;
    template<class F> size_t cvisit_all(F f) const;
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      void cvisit_all(ExecutionPolicy&& policy, F f) const;

    template<class F> bool visit_while(F f);
    template<class F> bool visit_while(F f) const;
    template<class F> bool cvisit_while(F f) const;
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      bool cvisit_while(ExecutionPolicy&& policy, F f) const;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> bool emplace(Args&&... args);
    bool insert(const value_type& obj);
    bool insert(value_type&& obj);
    template<class K> bool insert(K&& k);
    template<class InputIterator> size_type insert(InputIterator first, InputIterator last);
    size_type insert(std::initializer_list<value_type> il);

    template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
    template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);
    template<class F> bool insert_or_visit(const value_type& obj, F f);
    template<class F> bool insert_or_cvisit(const value_type& obj, F f);
    template<class F> bool insert_or_visit(value_type&& obj, F f);
    template<class F> bool insert_or_cvisit(value_type&& obj, F f);
    template<class K, class F> bool insert_or_visit(K&& k, F f);
    template<class K, class F> bool insert_or_cvisit(K&& k, F f);
    template<class InputIterator,class F>
      size_type insert_or_visit(InputIterator first, InputIterator last, F f);
    template<class InputIterator,class F>
      size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
    template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
    template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

    template<class... Args, class F1, class F2>
      bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);
    template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
    template<class K, class F1, class F2> bool insert_and_visit(K&& k, F1 f1, F2 f2);
    template<class K, class F1, class F2> bool insert_and_cvisit(K&& k, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

    size_type erase(const key_type& k);
    template<class K> size_type erase(const K& k);

    template<class F> size_type erase_if(const key_type& k, F f);
    template<class K, class F> size_type erase_if(const K& k, F f);
    template<class F> size_type erase_if(F f);
    template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

    void      swap(concurrent_flat_set& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
    void      clear() noexcept;

    template<class H2, class P2>
      size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    concurrent_flat_set(InputIterator, InputIterator, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_flat_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    concurrent_flat_set(std::initializer_list<T>, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_flat_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_flat_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> concurrent_flat_set<iter-value-type<InputIterator>,
                             boost::hash<iter-value-type<InputIterator>>,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_flat_set(InputIterator, InputIterator, Allocator)
      -> concurrent_flat_set<iter-value-type<InputIterator>,
                             boost::hash<iter-value-type<InputIterator>>,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    concurrent_flat_set(InputIterator, InputIterator, typename see below::size_type, Hash,
                        Allocator)
      -> concurrent_flat_set<iter-value-type<InputIterator>, Hash,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    concurrent_flat_set(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    concurrent_flat_set(std::initializer_list<T>, Allocator)
      -> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    concurrent_flat_set(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> concurrent_flat_set<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class Hash, class Pred, class Alloc>
    bool operator==(const concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
                    const concurrent_flat_set<Key, Hash, Pred, Alloc>& y);

  template<class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
                    const concurrent_flat_set<Key, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class Hash, class Pred, class Alloc>
    void swap(concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
              concurrent_flat_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class H, class P, class A, class Predicate>
    typename concurrent_flat_set<K, H, P, A>::size_type
       erase_if(concurrent_flat_set<K, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using concurrent_flat_set =
      boost::concurrent_flat_set<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可 移動插入 至容器中,且可從容器中 抹除

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與表格的值類型相同。 std::allocator_traits<Allocator>::pointerstd::allocator_traits<Allocator>::const_pointer 必須可以分別轉換為 value_type*const value_type*

資料表的元素會保留在內部儲存桶陣列中。元素會插入到由其雜湊碼決定的儲存桶中,但如果儲存桶已佔用 (衝突),則會使用原始位置附近的可用儲存桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或透過呼叫 rehash/reserve 來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor(),除了實作可能會決定允許更高載入的小型大小之外。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


並行需求和保證

需要在相同的 HashPred 常數執行個體上並行呼叫 operator(),而不會引入資料競爭。對於 AllocAllocator 或從 Allocator 重新繫結的任何配置器類型,需要在 Alloc 的相同執行個體 al 上並行呼叫以下作業,而不會引入資料競爭

  • Alloc 重新繫結的配置器 al 的複製建構

  • std::allocator_traits<Alloc>::allocate

  • std::allocator_traits<Alloc>::deallocate

  • std::allocator_traits<Alloc>::construct

  • std::allocator_traits<Alloc>::destroy

一般而言,如果 HashPredAllocator 這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。

除了銷毀之外,對同一個 concurrent_flat_set 實例上的任何操作的並行調用都不會引入資料競爭 — 也就是說,它們是執行緒安全的。

如果操作 op 被明確指定為阻塞於 x,其中 xboost::concurrent_flat_set 的實例,則對 x 的先前阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_flat_set 的阻塞操作會依序執行。

如果某個操作僅在發出內部重新雜湊時才阻塞於 x,則稱該操作阻塞於 x 的重新雜湊

當由 boost::concurrent_flat_set 在內部執行時,使用者提供的訪問函式對傳遞的元素執行的以下操作不會引入資料競爭

  • 對元素的讀取存取。

  • 對元素的不可變修改。

  • 對元素的可變修改。

    • 在接受兩個訪問函數的容器函數中,總是針對第一個函數。

    • 在名稱不包含 cvisit 的非常數容器函數中,針對最後一個(或唯一)的訪問函數。

任何插入或修改元素 eboost::concurrent_flat_set 操作 都會與對 e 的訪問函式的內部調用同步。

boost::concurrent_flat_set x 執行的訪問函式不允許調用 x 上的任何操作;只有在 y 上的並行未完成操作不直接或間接地存取 x 的情況下,才允許調用不同 boost::concurrent_flat_set 實例 y 上的操作。


組態巨集

BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK

在偵錯建置中(更精確地說,當 BOOST_ASSERT_IS_VOID 未定義時),會偵測到容器重入(從訪問 m 元素的函數中非法呼叫 m 上的操作),並透過 BOOST_ASSERT_MSG 發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。


BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集,以啟用表格的統計資訊計算。請注意,此選項會降低許多操作的整體效能。


常數

static constexpr size_type bulk_visit_size;

批量訪問 操作中內部使用的區塊大小。

建構子

預設建構函式
concurrent_flat_set();

使用 hasher() 作為雜湊函數,key_equal() 作為鍵相等謂詞,以及 allocator_type() 作為分配器,建構一個空表格。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit concurrent_flat_set(size_type n,
                             const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  concurrent_flat_set(InputIterator f, InputIterator l,
                      size_type n = implementation-defined,
                      const hasher& hf = hasher(),
                      const key_equal& eql = key_equal(),
                      const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
concurrent_flat_set(concurrent_flat_set const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的

並行性

other 上鎖定。


移動建構函式
concurrent_flat_set(concurrent_flat_set&& other);

移動建構函式。other 的內部桶陣列會直接傳輸到新表格。雜湊函式、謂詞和分配器是從 other 移動建構的。如果 啟用統計資訊,則從 other 傳輸內部統計資訊並呼叫 other.reset_stats()

並行性

other 上鎖定。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  concurrent_flat_set(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit concurrent_flat_set(Allocator const& a);

使用分配器 a,建構一個空表格。


具有分配器的複製建構函式
concurrent_flat_set(concurrent_flat_set const& other, Allocator const& a);

建構一個表格,複製 other 包含的元素、雜湊函數和謂詞,但使用分配器 a

並行性

other 上鎖定。


具備配置器的移動建構子
concurrent_flat_set(concurrent_flat_set&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接傳輸到新表格;否則,元素是從 other 的元素移動建構的。雜湊函式和謂詞是從 other 移動建構的,而分配器是從 a 複製建構的。如果 啟用統計資訊,則僅當 a == other.get_allocator() 時才從 other 傳輸內部統計資訊,並始終呼叫 other.reset_stats()

並行性

other 上鎖定。


從 unordered_flat_set 移動建構函式
concurrent_flat_set(unordered_flat_set<Key, Hash, Pred, Allocator>&& other);

unordered_flat_set 移動建構。other 的內部桶陣列會直接傳輸到新的容器。雜湊函式、謂詞和分配器是從 other 移動建構的。如果 啟用統計資訊,則從 other 傳輸內部統計資訊並呼叫 other.reset_stats()

複雜度

O(bucket_count())


初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il,
                    size_type n = implementation-defined
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a,並將來自 il 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
concurrent_flat_set(size_type n, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
concurrent_flat_set(size_type n, hasher const& hf, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  concurrent_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      concurrent_flat_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 以及預設雜湊函數和鍵相等謂詞,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                    const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 il 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~concurrent_flat_set();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
concurrent_flat_set& operator=(concurrent_flat_set const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入

並行性

阻塞於 *thisother


移動賦值
concurrent_flat_set& operator=(concurrent_flat_set&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value);

移動賦值運算子。銷毀先前存在的元素,從 other 交換雜湊函式和謂詞,並從 other 移動賦值分配器(如果存在 Alloc::propagate_on_container_move_assignmentAlloc::propagate_on_container_move_assignment::valuetrue)。如果在這一點上分配器等於 other.get_allocator(),則 other 的內部桶陣列會直接傳輸到 *this;否則,插入 other 元素的移動建構副本。如果 啟用統計資訊,則僅當最終分配器等於 other.get_allocator() 時才從 other 傳輸內部統計資訊,並始終呼叫 other.reset_stats()

並行性

阻塞於 *thisother


初始化列表賦值
concurrent_flat_set& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

並行性

阻塞於 *this


訪問

[c]visit
template<class F> size_t visit(const key_type& k, F f);
template<class F> size_t visit(const key_type& k, F f) const;
template<class F> size_t cvisit(const key_type& k, F f) const;
template<class K, class F> size_t visit(const K& k, F f);
template<class K, class F> size_t visit(const K& k, F f) const;
template<class K, class F> size_t cvisit(const K& k, F f) const;

如果存在鍵等效於 k 的元素 x,則使用對 x 的常數參考調用 f

傳回

訪問的元素數 (0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。


批量訪問
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
  size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

對於範圍 [first, last) 中的每個元素 k,如果容器中存在鍵等效於 k 的元素 x,則使用對 x 的常數參考調用 f

雖然功能上等同於單獨為每個鍵調用 [c]visit,但由於內部簡化優化,批量訪問通常執行速度更快。建議 std::distance(first,last) 至少為 bulk_visit_size 才能獲得效能提升:超過此大小,預期效能不會進一步提高。

需求

FwdIterator 是一個 LegacyForwardIterator (C++11 至 C++17),或滿足 std::forward_iterator (C++20 及更高版本)。對於 K = std::iterator_traits<FwdIterator>::value_typeK 要麼是 key_type,否則 Hash::is_transparentPred::is_transparent 是有效的成員 typedef。在後一種情況下,程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。

傳回

訪問的元素數。


[c]visit_all
template<class F> size_t visit_all(F f);
template<class F> size_t visit_all(F f) const;
template<class F> size_t cvisit_all(F f) const;

使用對表格中每個元素的常數參考連續調用 f

傳回

訪問的元素數。


平行 [c]visit_all
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> void cvisit_all(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的常數參考調用 f。根據指定的執行策略的語義進行平行化執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。


[c]visit_while
template<class F> bool visit_while(F f);
template<class F> bool visit_while(F f) const;
template<class F> bool cvisit_while(F f) const;

使用對表格中每個元素的常數參考連續調用 f,直到 f 返回 false 或訪問完所有元素。

傳回

如果 f 曾經傳回 false,則為 false


平行 [c]visit_while
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> bool cvisit_while(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的常數參考調用 f,直到 f 返回 false 或訪問完所有元素。根據指定的執行策略的語義進行平行化執行。

傳回

如果 f 曾經傳回 false,則為 false

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。

平行化表示執行不一定在 f 傳回 false 後立即完成,因此,f 可能會使用傳回值也為 false 的其他元素呼叫。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

表格中的元素數。

注意

在存在併發插入操作的情況下,傳回的值可能無法準確反映執行後表格的實際大小。


max_size
size_type max_size() const noexcept;
傳回

最大可能表格的 size()


修改器

emplace
template<class... Args> bool emplace(Args&&... args);

只有當表格中不存在具有等效鍵的元素時,才將使用引數 args 建構的物件插入表格中。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


複製插入
bool insert(const value_type& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


移動插入
bool insert(value_type&& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


透明插入
template<class K> bool insert(K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,此多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍
template<class InputIterator> size_type insert(InputIterator first, InputIterator last);

等同於

  while(first != last) this->emplace(*first++);
傳回

插入的元素數量。


插入初始化列表
size_type insert(std::initializer_list<value_type> il);

等同於

  this->insert(il.begin(), il.end());
傳回

插入的元素數量。


emplace_or_[c]visit
template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);

如果在表格中沒有具有等效鍵的元素,則在表格中插入使用參數 args 建構的物件。否則,使用對等效元素的常數參考調用 f

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f


複製 insert_or_[c]visit
template<class F> bool insert_or_visit(const value_type& obj, F f);
template<class F> bool insert_or_cvisit(const value_type& obj, F f);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj。否則,使用對等效元素的常數參考調用 f

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


移動 insert_or_[c]visit
template<class F> bool insert_or_visit(value_type&& obj, F f);
template<class F> bool insert_or_cvisit(value_type&& obj, F f);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj。否則,使用對等效元素的常數參考調用 f

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


透明 insert_or_[c]visit
template<class K, class F> bool insert_or_visit(K&& k, F f);
template<class K, class F> bool insert_or_cvisit(K&& k, F f);

當且僅當容器中沒有具有等效鍵的元素時,才在容器中插入從 std::forward<K>(k) 建構的元素。否則,使用對等效元素的常數參考調用 f

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,這些多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍或訪問
template<class InputIterator,class F>
    size_type insert_or_visit(InputIterator first, InputIterator last, F f);
template<class InputIterator,class F>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);

等同於

  while(first != last) this->emplace_or_[c]visit(*first++, f);
傳回

插入的元素數量。


插入初始化列表或訪問
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

等同於

  this->insert_or_[c]visit(il.begin(), il.end(), std::ref(f));
傳回

插入的元素數量。


emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);

如果在表格中沒有具有等效鍵的元素,則在表格中插入使用參數 args 建構的物件,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f1f2


複製 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


移動 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。


透明 insert_and_[c]visit
template<class K, class F1, class F2> bool insert_and_visit(K&& k, F1 f1, F2 f2);
template<class K, class F1, class F2> bool insert_and_cvisit(K&& k, F1 f1, F2 f2);

當且僅當容器中沒有具有等效鍵的元素時,才在容器中插入從 std::forward<K>(k) 建構的元素,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果發出重新雜湊,則會使指向元素的指標和參考失效。

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,這些多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍和訪問
template<class InputIterator,class F1, class F2>
    size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
template<class InputIterator,class F1, class F2>
    size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);

等同於

  while(first != last) this->emplace_and_[c]visit(*first++, f1, f2);
傳回

插入的元素數量。


插入初始化列表和訪問
template<class F1, class F2>
  size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
template<class F1, class F2>
  size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

等同於

  this->insert_and_[c]visit(il.begin(), il.end(), std::ref(f1), std::ref(f2));
傳回

插入的元素數量。


erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);

如果存在具有與 k 等效鍵的元素,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


依鍵刪除_if
template<class F> size_type erase_if(const key_type& k, F f);
template<class K, class F> size_type erase_if(const K& k, F f);

如果存在具有與 k 等效鍵的元素 x,且 f(x)true,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

只有當 hasherkey_equalf 擲回例外時,才會擲回例外。

注意

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>false 時,template<class K, class F> 多載才會參與多載解析。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


erase_if
template<class F> size_type erase_if(F f);

使用表格中每個元素的參考來連續調用 f,並刪除 f 返回 true 的元素。

傳回

已刪除的元素數量。

拋出

只有當 f 擲回例外時,才會擲回例外。


平行刪除_if
template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

使用表格中每個元素的參考來調用 f,並刪除 f 返回 true 的元素。根據指定的執行原則語意來平行處理執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,此多載才會參與多載解析。

不允許未排序的執行策略。


交換 (swap)
void swap(concurrent_flat_set& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將表格內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。

並行性

阻塞於 *thisother


清除 (clear)
void clear() noexcept;

刪除表格中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()

並行性

阻塞於 *this


合併 (merge)
template<class H2, class P2>
  size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。

傳回

插入的元素數量。

並行性

*thissource 上封鎖。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

表格的配置器。


hash_function
hasher hash_function() const;
傳回

表格的雜湊函式。


key_eq
key_equal key_eq() const;
傳回

表格的鍵相等謂詞。


Set 操作

計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等效鍵的元素數量(0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指示表格中是否存在鍵等於 k 的元素。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回表格的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_set 相容。


max_load
size_type max_load() const noexcept;
傳回

在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。

注意

建構、重新雜湊或清除後,表格的最大負載至少為 max_load_factor() * bucket_count()。在高負載條件下刪除時,此數目可能會減少。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,且負載因子小於或等於最大負載因子。在適用的情況下,這會擴大或縮小與表格相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

會使指向元素的指標和參考失效,並變更元素的順序。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函式可用於擴大或縮小表格中的儲存桶數目。

會使指向元素的指標和參考失效,並變更元素的順序。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


統計

get_stats
stats get_stats() const;
傳回

到目前為止表格執行的插入和查閱操作的統計說明。

注意

僅當 統計計算 啟用時才可用。


reset_stats
void reset_stats() noexcept;
作用

將表格保留的內部統計資料設定為零。

注意

僅當 統計計算 啟用時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class Hash, class Pred, class Alloc>
  bool operator==(const concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
                  const concurrent_flat_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 true

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


operator!=
template<class Key, class Hash, class Pred, class Alloc>
  bool operator!=(const concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
                  const concurrent_flat_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 false

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


交換

template<class Key, class Hash, class Pred, class Alloc>
  void swap(concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
            concurrent_flat_set<Key, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

等同於

x.swap(y);

erase_if

template<class K, class H, class P, class A, class Predicate>
  typename concurrent_flat_set<K, H, P, A>::size_type
    erase_if(concurrent_flat_set<K, H, P, A>& c, Predicate pred);

等同於

c.erase_if(pred);

序列化

concurrent_flat_set 可以透過此程式庫提供的 API 使用 Boost.Serialization 來歸檔/檢索。支援一般和 XML 歸檔。

將 concurrent_flat_set 儲存到歸檔

concurrent_flat_set x 的所有元素儲存到歸檔(XML 歸檔)ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。

並行性

x 上封鎖。


從歸檔載入 concurrent_flat_set

刪除 concurrent_flat_set x 的所有先前存在的元素,並從歸檔(XML 歸檔)ar 插入儲存到 ar 讀取的儲存區的原始 concurrent_flat_set other 的還原副本。

需求

x.key_equal() 在功能上等同於 other.key_equal()

並行性

x 上封鎖。

類別模板 concurrent_node_map

boost::concurrent_node_map — 一個基於節點的雜湊表,將唯一鍵與另一個值關聯,並允許並行插入、刪除、查找和存取元素,而無需外部同步機制。

即使它作為一個容器,boost::concurrent_node_map 並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作(beginend 等)。元素存取和修改是透過使用者提供的訪問函式完成,這些函式傳遞給 concurrent_node_map 操作,在內部以受控的方式執行。這種基於訪問的 API 允許低爭用的並行使用場景。

boost::concurrent_node_map 的內部資料結構與 boost::unordered_node_map 類似。與 boost::concurrent_flat_map 不同,以可能較低的效能為代價,提供了指標穩定性和節點處理功能。

概要

// #include <boost/unordered/concurrent_node_map.hpp>

namespace boost {
  template<class Key,
           class T,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
  class concurrent_node_map {
  public:
    // types
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = std::pair<const Key, T>;
    using init_type            = std::pair<
                                   typename std::remove_const<Key>::type,
                                   typename std::remove_const<T>::type
                                 >;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // constants
    static constexpr size_type bulk_visit_size = implementation-defined;

    // construct/copy/destroy
    concurrent_node_map();
    explicit concurrent_node_map(size_type n,
                                 const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    template<class InputIterator>
      concurrent_node_map(InputIterator f, InputIterator l,
                          size_type n = implementation-defined,
                          const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
    concurrent_node_map(const concurrent_node_map& other);
    concurrent_node_map(concurrent_node_map&& other);
    template<class InputIterator>
      concurrent_node_map(InputIterator f, InputIterator l,const allocator_type& a);
    explicit concurrent_node_map(const Allocator& a);
    concurrent_node_map(const concurrent_node_map& other, const Allocator& a);
    concurrent_node_map(concurrent_node_map&& other, const Allocator& a);
    concurrent_node_map(unordered_node_map<Key, T, Hash, Pred, Allocator>&& other);
    concurrent_node_map(std::initializer_list<value_type> il,
                        size_type n = implementation-defined
                        const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
    concurrent_node_map(size_type n, const allocator_type& a);
    concurrent_node_map(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      concurrent_node_map(InputIterator f, InputIterator l, size_type n,
                          const allocator_type& a);
    template<class InputIterator>
      concurrent_node_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);
    concurrent_node_map(std::initializer_list<value_type> il, const allocator_type& a);
    concurrent_node_map(std::initializer_list<value_type> il, size_type n,
                        const allocator_type& a);
    concurrent_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                        const allocator_type& a);
    ~concurrent_node_map();
    concurrent_node_map& operator=(const concurrent_node_map& other);
    concurrent_node_map& operator=(concurrent_node_map&& other) noexcept(
      (boost::allocator_traits<Allocator>::is_always_equal::value ||
       boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
       std::is_same<pointer, value_type*>::value);
    concurrent_node_map& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;


    // visitation
    template<class F> size_t visit(const key_type& k, F f);
    template<class F> size_t visit(const key_type& k, F f) const;
    template<class F> size_t cvisit(const key_type& k, F f) const;
    template<class K, class F> size_t visit(const K& k, F f);
    template<class K, class F> size_t visit(const K& k, F f) const;
    template<class K, class F> size_t cvisit(const K& k, F f) const;

    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f);
    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f) const;
    template<class FwdIterator, class F>
      size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

    template<class F> size_t visit_all(F f);
    template<class F> size_t visit_all(F f) const;
    template<class F> size_t cvisit_all(F f) const;
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      void cvisit_all(ExecutionPolicy&& policy, F f) const;

    template<class F> bool visit_while(F f);
    template<class F> bool visit_while(F f) const;
    template<class F> bool cvisit_while(F f) const;
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      bool cvisit_while(ExecutionPolicy&& policy, F f) const;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> bool emplace(Args&&... args);
    bool insert(const value_type& obj);
    bool insert(const init_type& obj);
    bool insert(value_type&& obj);
    bool insert(init_type&& obj);
    template<class InputIterator> size_type insert(InputIterator first, InputIterator last);
    size_type insert(std::initializer_list<value_type> il);
    insert_return_type insert(node_type&& nh);

    template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
    template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);
    template<class F> bool insert_or_visit(const value_type& obj, F f);
    template<class F> bool insert_or_cvisit(const value_type& obj, F f);
    template<class F> bool insert_or_visit(const init_type& obj, F f);
    template<class F> bool insert_or_cvisit(const init_type& obj, F f);
    template<class F> bool insert_or_visit(value_type&& obj, F f);
    template<class F> bool insert_or_cvisit(value_type&& obj, F f);
    template<class F> bool insert_or_visit(init_type&& obj, F f);
    template<class F> bool insert_or_cvisit(init_type&& obj, F f);
    template<class InputIterator,class F>
      size_type insert_or_visit(InputIterator first, InputIterator last, F f);
    template<class InputIterator,class F>
      size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
    template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
    template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);
    template<class F> insert_return_type insert_or_visit(node_type&& nh, F f);
    template<class F> insert_return_type insert_or_cvisit(node_type&& nh, F f);

    template<class... Args, class F1, class F2>
      bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);
    template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(const init_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const init_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(init_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2);
    template<class F1, class F2>
      insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2);

    template<class... Args> bool try_emplace(const key_type& k, Args&&... args);
    template<class... Args> bool try_emplace(key_type&& k, Args&&... args);
    template<class K, class... Args> bool try_emplace(K&& k, Args&&... args);

    template<class... Args, class F>
      bool try_emplace_or_visit(const key_type& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_cvisit(const key_type& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_visit(key_type&& k, Args&&... args, F&& f);
    template<class... Args, class F>
      bool try_emplace_or_cvisit(key_type&& k, Args&&... args, F&& f);
    template<class K, class... Args, class F>
      bool try_emplace_or_visit(K&& k, Args&&... args, F&& f);
    template<class K, class... Args, class F>
      bool try_emplace_or_cvisit(K&& k, Args&&... args, F&& f);

    template<class... Args, class F1, class F2>
      bool try_emplace_and_visit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_visit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class K, class... Args, class F1, class F2>
      bool try_emplace_and_visit(K&& k, Args&&... args, F1&& f1, F2&& f2);
    template<class K, class... Args, class F1, class F2>
      bool try_emplace_and_cvisit(K&& k, Args&&... args, F1&& f1, F2&& f2);


    template<class M> bool insert_or_assign(const key_type& k, M&& obj);
    template<class M> bool insert_or_assign(key_type&& k, M&& obj);
    template<class K, class M> bool insert_or_assign(K&& k, M&& obj);

    size_type erase(const key_type& k);
    template<class K> size_type erase(const K& k);

    template<class F> size_type erase_if(const key_type& k, F f);
    template<class K, class F> size_type erase_if(const K& k, F f);
    template<class F> size_type erase_if(F f);
    template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

    void      swap(concurrent_node_map& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

    node_type extract(const key_type& k);
    template<class K> node_type extract(const K& k);

    template<class F> node_type extract_if(const key_type& k, F f);
    template<class K, class F> node_type extract_if(const K& k, F f);

    void      clear() noexcept;

    template<class H2, class P2>
      size_type merge(concurrent_node_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      size_type merge(concurrent_node_map<Key, T, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-key-type<InputIterator>>,
           class Pred = std::equal_to<iter-key-type<InputIterator>>,
           class Allocator = std::allocator<iter-to-alloc-type<InputIterator>>>
    concurrent_node_map(InputIterator, InputIterator, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                             Pred, Allocator>;

  template<class Key, class T, class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<std::pair<const Key, T>>>
    concurrent_node_map(std::initializer_list<std::pair<Key, T>>,
                        typename see below::size_type = see below, Hash = Hash(),
                        Pred = Pred(), Allocator = Allocator())
      -> concurrent_node_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_node_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> concurrent_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                             boost::hash<iter-key-type<InputIterator>>,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_node_map(InputIterator, InputIterator, Allocator)
      -> concurrent_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
                             boost::hash<iter-key-type<InputIterator>>,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    concurrent_node_map(InputIterator, InputIterator, typename see below::size_type, Hash,
                        Allocator)
      -> concurrent_node_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash,
                             std::equal_to<iter-key-type<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    concurrent_node_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                        Allocator)
      -> concurrent_node_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Allocator>
    concurrent_node_map(std::initializer_list<std::pair<Key, T>>, Allocator)
      -> concurrent_node_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    concurrent_node_map(std::initializer_list<std::pair<Key, T>>, typename see below::size_type,
                        Hash, Allocator)
      -> concurrent_node_map<Key, T, Hash, std::equal_to<Key>, Allocator>;

  // Equality Comparisons
  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
                    const concurrent_node_map<Key, T, Hash, Pred, Alloc>& y);

  template<class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
                    const concurrent_node_map<Key, T, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class T, class Hash, class Pred, class Alloc>
    void swap(concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
              concurrent_node_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class T, class H, class P, class A, class Predicate>
    typename concurrent_node_map<K, T, H, P, A>::size_type
       erase_if(concurrent_node_map<K, T, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class T,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using concurrent_node_map =
      boost::concurrent_node_map<Key, T, Hash, Pred,
        std::pmr::polymorphic_allocator<std::pair<const Key, T>>>;
  }
}

描述

樣板參數

std::pair<const Key, T> 必須可以從任何可轉換為它的 std::pair 物件 原地建構到表格中,並且也必須可以從表格中 刪除

T

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

配置器的值類型與資料表的值類型相同。支援使用 花俏指標的配置器。

表格的元素節點保留在一個內部桶陣列中。節點會插入由其元素雜湊碼決定的桶中,但如果該桶已被佔用(衝突),則會使用原始位置附近的可用桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或透過呼叫 rehash/reserve 來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor(),除了實作可能會決定允許更高載入的小型大小之外。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


並行需求和保證

需要在相同的 HashPred 常數執行個體上並行呼叫 operator(),而不會引入資料競爭。對於 AllocAllocator 或從 Allocator 重新繫結的任何配置器類型,需要在 Alloc 的相同執行個體 al 上並行呼叫以下作業,而不會引入資料競爭

  • Alloc 重新繫結的配置器 al 的複製建構

  • std::allocator_traits<Alloc>::allocate

  • std::allocator_traits<Alloc>::deallocate

  • std::allocator_traits<Alloc>::construct

  • std::allocator_traits<Alloc>::destroy

一般而言,如果 HashPredAllocator 這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。

除了銷毀之外,對同一個 concurrent_node_map 實例上的任何操作的並行調用都不會引入資料競爭 — 也就是說,它們是執行緒安全的。

如果操作 op 被明確指定為阻塞於 x,其中 xboost::concurrent_node_map 的實例,則對 x 的先前阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_node_map 的阻塞操作會依序執行。

如果某個操作僅在發出內部重新雜湊時才阻塞於 x,則稱該操作阻塞於 x 的重新雜湊

當由 boost::concurrent_node_map 在內部執行時,使用者提供的訪問函式對傳遞的元素執行的以下操作不會引入資料競爭

  • 對元素的讀取存取。

  • 對元素的不可變修改。

  • 對元素的可變修改。

    • 在接受兩個訪問函數的容器函數中,總是針對第一個函數。

    • 在名稱不包含 cvisit 的非常數容器函數中,針對最後一個(或唯一)的訪問函數。

任何插入或修改元素 eboost::concurrent_node_map 操作 都會與對 e 的訪問函式的內部調用同步。

boost::concurrent_node_map x 執行的訪問函式不允許調用 x 上的任何操作;只有在 y 上的並行未完成操作不直接或間接地存取 x 的情況下,才允許調用不同 boost::concurrent_node_map 實例 y 上的操作。


組態巨集

BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK

在偵錯建置中(更精確地說,當 BOOST_ASSERT_IS_VOID 未定義時),會偵測到容器重入(從訪問 m 元素的函數中非法呼叫 m 上的操作),並透過 BOOST_ASSERT_MSG 發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。


BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集,以啟用表格的統計資訊計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined node_type;

一個用於保存提取的表格元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class NodeType>
struct insert_return_type // name is exposition only
{
  bool     inserted;
  NodeType node;
};

其中 NodeType = node_type


常數

static constexpr size_type bulk_visit_size;

批量訪問 操作中內部使用的區塊大小。


建構子

預設建構函式
concurrent_node_map();

使用 hasher() 作為雜湊函數,key_equal() 作為鍵相等謂詞,以及 allocator_type() 作為分配器,建構一個空表格。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit concurrent_node_map(size_type n,
                             const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  concurrent_node_map(InputIterator f, InputIterator l,
                      size_type n = implementation-defined,
                      const hasher& hf = hasher(),
                      const key_equal& eql = key_equal(),
                      const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
concurrent_node_map(concurrent_node_map const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的

並行性

other 上鎖定。


移動建構函式
concurrent_node_map(concurrent_node_map&& other);

移動建構函式。other 的內部桶陣列會直接傳輸到新表格。雜湊函式、謂詞和分配器是從 other 移動建構的。如果 啟用統計資訊,則從 other 傳輸內部統計資訊並呼叫 other.reset_stats()

並行性

other 上鎖定。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  concurrent_node_map(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit concurrent_node_map(Allocator const& a);

使用分配器 a,建構一個空表格。


具有分配器的複製建構函式
concurrent_node_map(concurrent_node_map const& other, Allocator const& a);

建構一個表格,複製 other 包含的元素、雜湊函數和謂詞,但使用分配器 a

並行性

other 上鎖定。


具備配置器的移動建構子
concurrent_node_map(concurrent_node_map&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接轉移到新表格;否則,元素會從 other 的元素移動建構而來。雜湊函式和述詞會從 other 移動建構而來,而配置器會從 a 複製建構而來。如果 啟用統計資訊,則當 a == other.get_allocator() 時,會轉移來自 other 的內部統計資訊,並總是呼叫 other.reset_stats()

並行性

other 上鎖定。


從 unordered_node_map 移動建構函式
concurrent_node_map(unordered_node_map<Key, T, Hash, Pred, Allocator>&& other);

unordered_node_map 移動建構。other 的內部 bucket 陣列會直接轉移到新容器。雜湊函式、述詞和配置器會從 other 移動建構而來。如果 啟用統計資訊,則會轉移來自 other 的內部統計資訊,並呼叫 other.reset_stats()

複雜度

O(bucket_count())


初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il,
                    size_type n = implementation-defined
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a,並將來自 il 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
concurrent_node_map(size_type n, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
concurrent_node_map(size_type n, hasher const& hf, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  concurrent_node_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      concurrent_node_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 以及預設雜湊函數和鍵相等謂詞,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                    const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 il 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~concurrent_node_map();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
concurrent_node_map& operator=(concurrent_node_map const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入

並行性

阻塞於 *thisother


移動賦值
concurrent_node_map& operator=(concurrent_node_map&& other)
  noexcept((boost::allocator_traits<Allocator>::is_always_equal::value ||
            boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) &&
            std::is_same<pointer, value_type*>::value);

移動賦值運算子。會銷毀先前存在的元素,交換來自 other 的雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則會從 other 移動賦值配置器。如果在這一點上配置器等於 other.get_allocator(),則 other 的內部 bucket 陣列會直接轉移到 *this;否則,會插入 other 元素的移動建構副本。如果 啟用統計資訊,則當最終配置器等於 other.get_allocator() 時,會轉移來自 other 的內部統計資訊,並總是呼叫 other.reset_stats()

並行性

阻塞於 *thisother


初始化列表賦值
concurrent_node_map& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

並行性

阻塞於 *this


訪問

[c]visit
template<class F> size_t visit(const key_type& k, F f);
template<class F> size_t visit(const key_type& k, F f) const;
template<class F> size_t cvisit(const key_type& k, F f) const;
template<class K, class F> size_t visit(const K& k, F f);
template<class K, class F> size_t visit(const K& k, F f) const;
template<class K, class F> size_t cvisit(const K& k, F f) const;

如果存在一個與 k 等效的鍵的元素 x,則使用對 x 的引用呼叫 f。只有當 *this 是常數時,此引用才是常數。

傳回

訪問的元素數 (0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。


批量訪問
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
  size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

對於範圍 [first, last) 中的每個元素 k,如果容器中存在一個與 k 等效的鍵的元素 x,則使用對 x 的引用呼叫 f。只有當 *this 是常數時,此引用才是常數。

儘管在功能上等同於個別調用每個鍵的 [c]visit,但由於內部的最佳化,批量訪問通常執行得更快。建議 std::distance(first,last) 至少為 bulk_visit_size 以享受效能提升:超過此大小,預計效能不會進一步提高。

需求

FwdIterator 是一個 LegacyForwardIterator (C++11 至 C++17),或滿足 std::forward_iterator (C++20 及更高版本)。對於 K = std::iterator_traits<FwdIterator>::value_typeK 要麼是 key_type,否則 Hash::is_transparentPred::is_transparent 是有效的成員 typedef。在後一種情況下,程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。

傳回

訪問的元素數。


[c]visit_all
template<class F> size_t visit_all(F f);
template<class F> size_t visit_all(F f) const;
template<class F> size_t cvisit_all(F f) const;

使用對表格中每個元素的引用,依序呼叫 f。只有當 *this 是常數時,此引用才是常數。

傳回

訪問的元素數。


平行 [c]visit_all
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> void cvisit_all(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的引用,呼叫 f。只有當 *this 是常數時,此引用才是常數。執行會根據指定的執行策略語意進行平行處理。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。


[c]visit_while
template<class F> bool visit_while(F f);
template<class F> bool visit_while(F f) const;
template<class F> bool cvisit_while(F f) const;

使用對表格中每個元素的引用,依序呼叫 f,直到 f 傳回 false 或所有元素都被訪問完為止。只有當 *this 是常數時,對元素的引用才是常數。

傳回

如果 f 曾經傳回 false,則為 false


平行 [c]visit_while
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> bool cvisit_while(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的引用,呼叫 f,直到 f 傳回 false 或所有元素都被訪問完為止。只有當 *this 是常數時,對元素的引用才是常數。執行會根據指定的執行策略語意進行平行處理。

傳回

如果 f 曾經傳回 false,則為 false

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。

平行化表示執行不一定在 f 傳回 false 後立即完成,因此,f 可能會使用傳回值也為 false 的其他元素呼叫。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

表格中的元素數。

注意

在存在併發插入操作的情況下,傳回的值可能無法準確反映執行後表格的實際大小。


max_size
size_type max_size() const noexcept;
傳回

最大可能表格的 size()


修改器

emplace
template<class... Args> bool emplace(Args&&... args);

只有當表格中不存在具有等效鍵的元素時,才將使用引數 args 建構的物件插入表格中。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 args…​ 的形式為 k,v,則會延遲建構整個物件,直到確定應插入元素,僅使用 k 引數進行檢查。


複製插入
bool insert(const value_type& obj);
bool insert(const init_type& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 const value_type&const init_type&,不會產生歧義,並會選取 init_type 多載。


移動插入
bool insert(value_type&& obj);
bool insert(init_type&& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

形式為 insert(x) 的呼叫,其中 x 可以同等轉換為 value_type&&init_type&&,不會產生歧義,並會選取 init_type 多載。


插入迭代器範圍
template<class InputIterator> size_type insert(InputIterator first, InputIterator last);

等同於

  while(first != last) this->emplace(*first++);
傳回

插入的元素數量。


插入初始化列表
size_type insert(std::initializer_list<value_type> il);

等同於

  this->insert(il.begin(), il.end());
傳回

插入的元素數量。


插入節點
insert_return_type insert(node_type&& nh);

如果 nh 不為空,則僅當表格中沒有與 nh.key() 等效的鍵的元素時,才會將相關元素插入表格。當函式返回時,nh 為空。

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


emplace_or_[c]visit
template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);

如果表中沒有具有等效鍵的元素,則將使用參數 args 建構的物件插入表中。否則,會使用對等效元素的參考來調用 f;當使用 emplace_or_cvisit 時,此參考為 const。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f


複製 insert_or_[c]visit
template<class F> bool insert_or_visit(const value_type& obj, F f);
template<class F> bool insert_or_cvisit(const value_type& obj, F f);
template<class F> bool insert_or_visit(const init_type& obj, F f);
template<class F> bool insert_or_cvisit(const init_type& obj, F f);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

insert_or_[c]visit(obj, f) 形式的調用中,只有當 std::remove_cv<std::remove_reference<decltype(obj)>::type>::typevalue_type 時,接受 const value_type& 參數的多載才會參與多載解析。


移動 insert_or_[c]visit
template<class F> bool insert_or_visit(value_type&& obj, F f);
template<class F> bool insert_or_cvisit(value_type&& obj, F f);
template<class F> bool insert_or_visit(init_type&& obj, F f);
template<class F> bool insert_or_cvisit(init_type&& obj, F f);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

insert_or_[c]visit(obj, f) 形式的調用中,只有當 std::remove_reference<decltype(obj)>::typevalue_type 時,接受 value_type&& 參數的多載才會參與多載解析。


插入迭代器範圍或訪問
template<class InputIterator,class F>
    size_type insert_or_visit(InputIterator first, InputIterator last, F f);
template<class InputIterator,class F>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);

等同於

  while(first != last) this->emplace_or_[c]visit(*first++, f);
傳回

插入的元素數量。


插入初始化列表或訪問
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

等同於

  this->insert_or_[c]visit(il.begin(), il.end(), std::ref(f));
傳回

插入的元素數量。


插入節點或訪問
template<class F> insert_return_type insert_or_visit(node_type&& nh, F f);
template<class F> insert_return_type insert_or_cvisit(node_type&& nh, F f);

如果 nh 為空,則不執行任何操作。否則,僅當表格中沒有與 nh.key() 等效的鍵的元素時,才會將相關元素插入表格。否則,會使用對等元素的參考來調用 f;如果使用 insert_or_cvisit,則此參考為 const。

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果除了呼叫 hasher 或呼叫 f 之外的操作擲回例外,則函式沒有任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);

如果表中沒有具有等效鍵的元素,則將使用參數 args 建構的物件插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 emplace_and_cvisit 時,此參考為 const。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f1f2


複製 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_visit(const init_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const init_type& obj, F1 f1, F2 f2);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

insert_and_[c]visit(obj, f1, f2) 形式的調用中,只有當 std::remove_cv<std::remove_reference<decltype(obj)>::type>::typevalue_type 時,接受 const value_type& 參數的多載才會參與多載解析。


移動 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_visit(init_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

insert_and_[c]visit(obj, f1, f2) 形式的調用中,只有當 std::remove_reference<decltype(obj)>::typevalue_type 時,接受 value_type&& 參數的多載才會參與多載解析。


插入迭代器範圍和訪問
template<class InputIterator, class F1, class F2>
    size_type insert_or_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
template<class InputIterator, class F1, class F2>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F1 f2, F2 f2);

等同於

  while(first != last) this->emplace_and_[c]visit(*first++, f1, f2);
傳回

插入的元素數量。


插入初始化列表和訪問
template<class F1, class F2>
  size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
template<class F1, class F2>
  size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

等同於

  this->insert_and_[c]visit(il.begin(), il.end(), std::ref(f1), std::ref(f2));
傳回

插入的元素數量。


插入節點並訪問
template<class F1, class F2>
  insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2);
template<class F1, class F2>
  insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2);

如果 nh 為空,則不執行任何操作。否則,僅當表格中沒有與 nh.key() 等效的鍵的元素時,才會將相關元素插入表格,然後使用對新插入元素的非 const 參考來調用 f1。否則,會使用對等元素的參考來調用 f2;如果使用 insert_or_cvisit,則此參考為 const。

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果除了呼叫 hasher 或呼叫 f1f2 之外的操作擲回例外,則函式沒有任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


try_emplace
template<class... Args> bool try_emplace(const key_type& k, Args&&... args);
template<class... Args> bool try_emplace(key_type&& k, Args&&... args);
template<class K, class... Args> bool try_emplace(K&& k, Args&&... args);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此函式與 emplace 類似,不同之處在於,如果存在具有等效鍵的元素,則不會建構 value_type;否則,建構的形式為

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

emplace 不同,後者只是將所有引數轉送到 value_type 的建構函式。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


try_emplace_or_[c]visit
template<class... Args, class F>
  bool try_emplace_or_visit(const key_type& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_cvisit(const key_type& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_visit(key_type&& k, Args&&... args, F&& f);
template<class... Args, class F>
  bool try_emplace_or_cvisit(key_type&& k, Args&&... args, F&& f);
template<class K, class... Args, class F>
  bool try_emplace_or_visit(K&& k, Args&&... args, F&& f);
template<class K, class... Args, class F>
  bool try_emplace_or_cvisit(K&& k, Args&&... args, F&& f);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中。否則,會使用對等效元素的參考來調用 f;當使用 *_cvisit 多載時,此參考為 const。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果存在具有等效鍵的元素,則不會建構任何 value_type;否則,建構形式為

// first four overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// last two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


try_emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool try_emplace_and_visit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(const key_type& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_visit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(key_type&& k, Args&&... args, F1&& f1, F2&& f2);
template<class K, class... Args, class F1, class F2>
  bool try_emplace_and_visit(K&& k, Args&&... args, F1&& f1, F2&& f2);
template<class K, class... Args, class F1, class F2>
  bool try_emplace_and_cvisit(K&& k, Args&&... args, F1&& f1, F2&& f2);

如果表中沒有包含鍵 k 的現有元素,則將使用 kargs 建構的元素插入表中,然後使用對新建立元素的非常數參考來調用 f1。否則,會使用對等效元素的參考來調用 f2;當使用 *_cvisit 多載時,此參考為 const。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果存在具有等效鍵的元素,則不會建構任何 value_type;否則,建構形式為

// first four overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

// last two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<Args>(args)...))

介面僅供展示,因為 C++ 不允許在可變引數包之後宣告參數 f1f2

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class... Args, class F1, class F2> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


insert_or_assign
template<class M> bool insert_or_assign(const key_type& k, M&& obj);
template<class M> bool insert_or_assign(key_type&& k, M&& obj);
template<class K, class M> bool insert_or_assign(K&& k, M&& obj);

將新元素插入表中,或透過賦值給包含的值來更新現有元素。

如果存在具有鍵值 k 的元素,則透過賦值 std::forward<M>(obj) 來更新它。

如果沒有此類元素,則會將其新增至表格中,如下所示

// first two overloads
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<Key>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))

// third overload
value_type(std::piecewise_construct,
           std::forward_as_tuple(std::forward<K>(k)),
           std::forward_as_tuple(std::forward<M>(obj)))
傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

只有在 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class M> 才會參與多載解析。函式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可以啟用異質查詢,從而避免實例化 Key 類型的成本。


erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);

如果存在具有與 k 等效鍵的元素,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


依鍵刪除_if
template<class F> size_type erase_if(const key_type& k, F f);
template<class K, class F> size_type erase_if(const K& k, F f);

如果存在具有與 k 等效鍵的元素 x,且 f(x)true,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

只有當 hasherkey_equalf 擲回例外時,才會擲回例外。

注意

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>false 時,template<class K, class F> 多載才會參與多載解析。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


erase_if
template<class F> size_type erase_if(F f);

使用表格中每個元素的參考來連續調用 f,並刪除 f 返回 true 的元素。

傳回

已刪除的元素數量。

拋出

只有當 f 擲回例外時,才會擲回例外。


平行刪除_if
template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

使用表格中每個元素的參考來調用 f,並刪除 f 返回 true 的元素。根據指定的執行原則語意來平行處理執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,此多載才會參與多載解析。

不允許未排序的執行策略。


交換 (swap)
void swap(concurrent_node_map& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將表格內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。

並行性

阻塞於 *thisother


提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

提取具有與 k 等效鍵的元素(如果存在)。

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


extract_if
template<class F> node_type extract_if(const key_type& k, F f);
template<class K, class F> node_type extract_if(K&& k, F f);

如果存在且 f(x)true,則會提取具有與 k 等效的鍵的元素 x

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅當 hasherkey_equalf 擲回例外時才會擲回例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


清除 (clear)
void clear() noexcept;

刪除表格中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()

並行性

阻塞於 *this


合併 (merge)
template<class H2, class P2>
  size_type merge(concurrent_node_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
  size_type merge(concurrent_node_map<Key, T, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。

傳回

插入的元素數量。

並行性

*thissource 上封鎖。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

表格的配置器。


hash_function
hasher hash_function() const;
傳回

表格的雜湊函式。


key_eq
key_equal key_eq() const;
傳回

表格的鍵相等謂詞。


Map 操作

計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等效鍵的元素數量(0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指示表格中是否存在鍵等於 k 的元素。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回表格的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_map 相容。


max_load
size_type max_load() const noexcept;
傳回

在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。

注意

建構、重新雜湊或清除後,表格的最大負載至少為 max_load_factor() * bucket_count()。在高負載條件下刪除時,此數目可能會減少。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,且負載因子小於或等於最大負載因子。在適用的情況下,這會擴大或縮小與表格相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函式可用於擴大或縮小表格中的儲存桶數目。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


統計

get_stats
stats get_stats() const;
傳回

到目前為止表格執行的插入和查閱操作的統計說明。

注意

僅當 啟用統計資訊計算時才可用。


reset_stats
void reset_stats() noexcept;
作用

將表格保留的內部統計資料設定為零。

注意

僅當 啟用統計資訊計算時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_­type 參數類型指的是推導指南推導的表格類型的 size_­type 成員類型。其預設值與選取的建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only
iter-key-type
template<class InputIterator>
  using iter-key-type = std::remove_const_t<
    std::tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only
iter-mapped-type
template<class InputIterator>
  using iter-mapped-type =
    std::tuple_element_t<1, iter-value-type<InputIterator>>;  // exposition only
iter-to-alloc-type
template<class InputIterator>
  using iter-to-alloc-type = std::pair<
    std::add_const_t<std::tuple_element_t<0, iter-value-type<InputIterator>>>,
    std::tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only

相等比較

operator==
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator==(const concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
                  const concurrent_node_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 true

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


operator!=
template<class Key, class T, class Hash, class Pred, class Alloc>
  bool operator!=(const concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
                  const concurrent_node_map<Key, T, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 false

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


交換

template<class Key, class T, class Hash, class Pred, class Alloc>
  void swap(concurrent_node_map<Key, T, Hash, Pred, Alloc>& x,
            concurrent_node_map<Key, T, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

等同於

x.swap(y);

erase_if

template<class K, class T, class H, class P, class A, class Predicate>
  typename concurrent_node_map<K, T, H, P, A>::size_type
    erase_if(concurrent_node_map<K, T, H, P, A>& c, Predicate pred);

等同於

c.erase_if(pred);

序列化

可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 concurrent_node_map。支援一般封存和 XML 封存。

將 concurrent_node_map 儲存到封存

concurrent_node_map x 的所有元素儲存到封存 (XML 封存) ar

需求

std::remove_const<key_type>::typestd::remove_const<mapped_type>::type 是可序列化的 (可 XML 序列化),且它們支援 Boost.Serialization save_construct_data/load_construct_data 協定(由 DefaultConstructible 類型自動支援)。

並行性

x 上封鎖。


從封存載入 concurrent_node_map

刪除 concurrent_node_map x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入已還原的原始 concurrent_node_map other 的元素副本,這些副本已儲存到 ar 讀取的儲存空間。

需求

x.key_equal() 在功能上等同於 other.key_equal()

並行性

x 上封鎖。

類別模板 concurrent_node_set

boost::concurrent_node_set — 一個基於節點的雜湊表,用於儲存唯一值,並允許並行元素插入、刪除、查找和存取,而無需外部同步機制。

儘管它充當容器,但 boost::concurrent_node_set 並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作 (beginend 等)。元素存取是透過使用者提供的訪問函式來完成,這些函式會傳遞到 concurrent_node_set 操作,並在其中以受控制的方式內部執行。這種基於訪問的 API 允許低競爭的並行使用場景。

boost::concurrent_node_set 的內部資料結構與 boost::unordered_node_set 的相似。與 boost::concurrent_flat_set 不同,提供指標穩定性和節點處理功能,但可能會犧牲較低的效能。

概要

// #include <boost/unordered/concurrent_node_set.hpp>

namespace boost {
  template<class Key,
           class Hash = boost::hash<Key>,
           class Pred = std::equal_to<Key>,
           class Allocator = std::allocator<Key>>
  class concurrent_node_set {
  public:
    // types
    using key_type             = Key;
    using value_type           = Key;
    using init_type            = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer        = typename std::allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = std::size_t;
    using difference_type      = std::ptrdiff_t;

    using node_type            = implementation-defined;
    using insert_return_type   = implementation-defined;

    using stats                = stats-type; // if statistics are enabled

    // constants
    static constexpr size_type bulk_visit_size = implementation-defined;

    // construct/copy/destroy
    concurrent_node_set();
    explicit concurrent_node_set(size_type n,
                                 const hasher& hf = hasher(),
                                 const key_equal& eql = key_equal(),
                                 const allocator_type& a = allocator_type());
    template<class InputIterator>
      concurrent_node_set(InputIterator f, InputIterator l,
                          size_type n = implementation-defined,
                          const hasher& hf = hasher(),
                          const key_equal& eql = key_equal(),
                          const allocator_type& a = allocator_type());
    concurrent_node_set(const concurrent_node_set& other);
    concurrent_node_set(concurrent_node_set&& other);
    template<class InputIterator>
      concurrent_node_set(InputIterator f, InputIterator l,const allocator_type& a);
    explicit concurrent_node_set(const Allocator& a);
    concurrent_node_set(const concurrent_node_set& other, const Allocator& a);
    concurrent_node_set(concurrent_node_set&& other, const Allocator& a);
    concurrent_node_set(unordered_node_set<Key, Hash, Pred, Allocator>&& other);
    concurrent_node_set(std::initializer_list<value_type> il,
                        size_type n = implementation-defined
                        const hasher& hf = hasher(),
                        const key_equal& eql = key_equal(),
                        const allocator_type& a = allocator_type());
    concurrent_node_set(size_type n, const allocator_type& a);
    concurrent_node_set(size_type n, const hasher& hf, const allocator_type& a);
    template<class InputIterator>
      concurrent_node_set(InputIterator f, InputIterator l, size_type n,
                          const allocator_type& a);
    template<class InputIterator>
      concurrent_node_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);
    concurrent_node_set(std::initializer_list<value_type> il, const allocator_type& a);
    concurrent_node_set(std::initializer_list<value_type> il, size_type n,
                        const allocator_type& a);
    concurrent_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                        const allocator_type& a);
    ~concurrent_node_set();
    concurrent_node_set& operator=(const concurrent_node_set& other);
    concurrent_node_set& operator=(concurrent_node_set&& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
              boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value);
    concurrent_node_set& operator=(std::initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;


    // visitation
    template<class F> size_t visit(const key_type& k, F f);
    template<class F> size_t visit(const key_type& k, F f) const;
    template<class F> size_t cvisit(const key_type& k, F f) const;
    template<class K, class F> size_t visit(const K& k, F f);
    template<class K, class F> size_t visit(const K& k, F f) const;
    template<class K, class F> size_t cvisit(const K& k, F f) const;

    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f);
    template<class FwdIterator, class F>
      size_t visit(FwdIterator first, FwdIterator last, F f) const;
    template<class FwdIterator, class F>
      size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

    template<class F> size_t visit_all(F f);
    template<class F> size_t visit_all(F f) const;
    template<class F> size_t cvisit_all(F f) const;
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      void visit_all(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      void cvisit_all(ExecutionPolicy&& policy, F f) const;

    template<class F> bool visit_while(F f);
    template<class F> bool visit_while(F f) const;
    template<class F> bool cvisit_while(F f) const;
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f);
    template<class ExecutionPolicy, class F>
      bool visit_while(ExecutionPolicy&& policy, F f) const;
    template<class ExecutionPolicy, class F>
      bool cvisit_while(ExecutionPolicy&& policy, F f) const;

    // capacity
    [[nodiscard]] bool empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers
    template<class... Args> bool emplace(Args&&... args);
    bool insert(const value_type& obj);
    bool insert(value_type&& obj);
    template<class K> bool insert(K&& k);
    template<class InputIterator> size_type insert(InputIterator first, InputIterator last);
    size_type insert(std::initializer_list<value_type> il);
    insert_return_type insert(node_type&& nh);

    template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
    template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);
    template<class F> bool insert_or_visit(const value_type& obj, F f);
    template<class F> bool insert_or_cvisit(const value_type& obj, F f);
    template<class F> bool insert_or_visit(value_type&& obj, F f);
    template<class F> bool insert_or_cvisit(value_type&& obj, F f);
    template<class K, class F> bool insert_or_visit(K&& k, F f);
    template<class K, class F> bool insert_or_cvisit(K&& k, F f);
    template<class InputIterator,class F>
      size_type insert_or_visit(InputIterator first, InputIterator last, F f);
    template<class InputIterator,class F>
      size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);
    template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
    template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);
    template<class F> insert_return_type insert_or_visit(node_type&& nh, F f);
    template<class F> insert_return_type insert_or_cvisit(node_type&& nh, F f);

    template<class... Args, class F1, class F2>
      bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2);
    template<class... Args, class F1, class F2>
      bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2);
    template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
    template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);
    template<class K, class F1, class F2> bool insert_and_visit(K&& k, F1 f1, F2 f2);
    template<class K, class F1, class F2> bool insert_and_cvisit(K&& k, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class InputIterator,class F1, class F2>
      size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);
    template<class F1, class F2>
      insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2);
    template<class F1, class F2>
      insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2);

    size_type erase(const key_type& k);
    template<class K> size_type erase(const K& k);

    template<class F> size_type erase_if(const key_type& k, F f);
    template<class K, class F> size_type erase_if(const K& k, F f);
    template<class F> size_type erase_if(F f);
    template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

    void      swap(concurrent_node_set& other)
      noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
               boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

    node_type extract(const key_type& k);
    template<class K> node_type extract(const K& k);

    template<class F> node_type extract_if(const key_type& k, F f);
    template<class K, class F> node_type extract_if(const K& k, F f);

    void      clear() noexcept;

    template<class H2, class P2>
      size_type merge(concurrent_node_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      size_type merge(concurrent_node_set<Key, H2, P2, Allocator>&& source);

    // observers
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations
    size_type        count(const key_type& k) const;
    template<class K>
      size_type      count(const K& k) const;
    bool             contains(const key_type& k) const;
    template<class K>
      bool           contains(const K& k) const;

    // bucket interface
    size_type bucket_count() const noexcept;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    size_type max_load() const noexcept;
    void rehash(size_type n);
    void reserve(size_type n);

    // statistics (if enabled)
    stats get_stats() const;
    void reset_stats() noexcept;
  };

  // Deduction Guides
  template<class InputIterator,
           class Hash = boost::hash<iter-value-type<InputIterator>>,
           class Pred = std::equal_to<iter-value-type<InputIterator>>,
           class Allocator = std::allocator<iter-value-type<InputIterator>>>
    concurrent_node_set(InputIterator, InputIterator, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_node_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>;

  template<class T, class Hash = boost::hash<T>, class Pred = std::equal_to<T>,
           class Allocator = std::allocator<T>>
    concurrent_node_set(std::initializer_list<T>, typename see below::size_type = see below,
                        Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> concurrent_node_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_node_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> concurrent_node_set<iter-value-type<InputIterator>,
                             boost::hash<iter-value-type<InputIterator>>,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    concurrent_node_set(InputIterator, InputIterator, Allocator)
      -> concurrent_node_set<iter-value-type<InputIterator>,
                             boost::hash<iter-value-type<InputIterator>>,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    concurrent_node_set(InputIterator, InputIterator, typename see below::size_type, Hash,
                        Allocator)
      -> concurrent_node_set<iter-value-type<InputIterator>, Hash,
                             std::equal_to<iter-value-type<InputIterator>>, Allocator>;

  template<class T, class Allocator>
    concurrent_node_set(std::initializer_list<T>, typename see below::size_type, Allocator)
      -> concurrent_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Allocator>
    concurrent_node_set(std::initializer_list<T>, Allocator)
      -> concurrent_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    concurrent_node_set(std::initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> concurrent_node_set<T, Hash, std::equal_to<T>, Allocator>;

  // Equality Comparisons
  template<class Key, class Hash, class Pred, class Alloc>
    bool operator==(const concurrent_node_set<Key, Hash, Pred, Alloc>& x,
                    const concurrent_node_set<Key, Hash, Pred, Alloc>& y);

  template<class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const concurrent_node_set<Key, Hash, Pred, Alloc>& x,
                    const concurrent_node_set<Key, Hash, Pred, Alloc>& y);

  // swap
  template<class Key, class Hash, class Pred, class Alloc>
    void swap(concurrent_node_set<Key, Hash, Pred, Alloc>& x,
              concurrent_node_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  // Erasure
  template<class K, class H, class P, class A, class Predicate>
    typename concurrent_node_set<K, H, P, A>::size_type
       erase_if(concurrent_node_set<K, H, P, A>& c, Predicate pred);

  // Pmr aliases (C++17 and up)
  namespace unordered::pmr {
    template<class Key,
             class Hash = boost::hash<Key>,
             class Pred = std::equal_to<Key>>
    using concurrent_node_set =
      boost::concurrent_node_set<Key, Hash, Pred,
        std::pmr::polymorphic_allocator<Key>>;
  }
}

描述

樣板參數

Key 必須可 移動插入 至容器中,且可從容器中 抹除

雜湊

一個一元函數物件類型,作為 Key 的雜湊函數。它接受一個 Key 類型的單一引數,並傳回 std::size_t 類型的值。

Pred

一個二元函數物件,在 Key 類型的值上誘導等價關係。它接受兩個 Key 類型的引數,並傳回 bool 類型的值。

分配器

一個分配器,其值類型與表格的值類型相同。 std::allocator_traits<Allocator>::pointerstd::allocator_traits<Allocator>::const_pointer 必須可以分別轉換為 value_type*const value_type*

表格的元素節點保留在一個內部桶陣列中。節點會插入由其元素雜湊碼決定的桶中,但如果該桶已被佔用(衝突),則會使用原始位置附近的可用桶。

儲存桶陣列的大小可以透過呼叫 insert/emplace 自動增加,或透過呼叫 rehash/reserve 來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor(),除了實作可能會決定允許更高載入的小型大小之外。

如果 hash_is_avalanching<Hash>::valuetrue,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。


並行需求和保證

需要在相同的 HashPred 常數執行個體上並行呼叫 operator(),而不會引入資料競爭。對於 AllocAllocator 或從 Allocator 重新繫結的任何配置器類型,需要在 Alloc 的相同執行個體 al 上並行呼叫以下作業,而不會引入資料競爭

  • Alloc 重新繫結的配置器 al 的複製建構

  • std::allocator_traits<Alloc>::allocate

  • std::allocator_traits<Alloc>::deallocate

  • std::allocator_traits<Alloc>::construct

  • std::allocator_traits<Alloc>::destroy

一般而言,如果 HashPredAllocator 這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。

除了銷毀之外,並行調用 concurrent_node_set 同一執行個體上的任何操作都不會引入資料競爭 — 也就是說,它們是執行緒安全的。

如果操作 op 明確指定為封鎖 x,其中 xboost::concurrent_node_set 的執行個體,則先前對 x 的封鎖操作會與 op 同步。因此,在多執行緒情境中,對同一 concurrent_node_set 的封鎖操作會循序執行。

如果某個操作僅在發出內部重新雜湊時才阻塞於 x,則稱該操作阻塞於 x 的重新雜湊

當由 boost::concurrent_node_set 內部執行時,使用者提供的訪問函式在傳遞的元素上執行以下操作不會引入資料競爭

  • 對元素的讀取存取。

  • 對元素的不可變修改。

  • 對元素的可變修改。

    • 在接受兩個訪問函數的容器函數中,總是針對第一個函數。

    • 在名稱不包含 cvisit 的非常數容器函數中,針對最後一個(或唯一)的訪問函數。

任何插入或修改元素 eboost::concurrent_node_set 操作都會與在 e 上訪問函式的內部調用同步。

boost::concurrent_node_set x 執行的訪問函式不允許調用 x 上的任何操作;只有在 y 上的並行未完成操作不會直接或間接存取 x 時,才允許調用不同 boost::concurrent_node_set 執行個體 y 上的操作。


組態巨集

BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK

在偵錯建置中(更精確地說,當 BOOST_ASSERT_IS_VOID 未定義時),會偵測到容器重入(從訪問 m 元素的函數中非法呼叫 m 上的操作),並透過 BOOST_ASSERT_MSG 發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。


BOOST_UNORDERED_ENABLE_STATS

全域定義此巨集,以啟用表格的統計資訊計算。請注意,此選項會降低許多操作的整體效能。


型別定義

typedef implementation-defined node_type;

一個用於保存提取的表格元素的類別,建模 NodeHandle


typedef implementation-defined insert_return_type;

內部類別樣板的特化

template<class NodeType>
struct insert_return_type // name is exposition only
{
  bool     inserted;
  NodeType node;
};

其中 NodeType = node_type


常數

static constexpr size_type bulk_visit_size;

批量訪問操作中內部使用的區塊大小。

建構子

預設建構函式
concurrent_node_set();

使用 hasher() 作為雜湊函數,key_equal() 作為鍵相等謂詞,以及 allocator_type() 作為分配器,建構一個空表格。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


儲存桶計數建構函式
explicit concurrent_node_set(size_type n,
                             const hasher& hf = hasher(),
                             const key_equal& eql = key_equal(),
                             const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


迭代器範圍建構函式
template<class InputIterator>
  concurrent_node_set(InputIterator f, InputIterator l,
                      size_type n = implementation-defined,
                      const hasher& hf = hasher(),
                      const key_equal& eql = key_equal(),
                      const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a 作為分配器,並將來自 [f, l) 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


複製建構函式
concurrent_node_set(concurrent_node_set const& other);

複製建構子。複製包含的元素、雜湊函數、述詞和配置器。

如果 Allocator::select_on_container_copy_construction 存在並具有正確的簽章,則分配器將從其結果中建構。

需求

value_type 是可複製建構的

並行性

other 上鎖定。


移動建構函式
concurrent_node_set(concurrent_node_set&& other);

移動建構函式。other 的內部 bucket 陣列會直接轉移到新表格。雜湊函式、述詞和配置器會從 other 移動建構而來。如果 啟用統計資訊,則會轉移來自 other 的內部統計資訊,並呼叫 other.reset_stats()

並行性

other 上鎖定。


具有分配器的迭代器範圍建構函式
template<class InputIterator>
  concurrent_node_set(InputIterator f, InputIterator l, const allocator_type& a);

使用 a 作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


分配器建構函式
explicit concurrent_node_set(Allocator const& a);

使用分配器 a,建構一個空表格。


具有分配器的複製建構函式
concurrent_node_set(concurrent_node_set const& other, Allocator const& a);

建構一個表格,複製 other 包含的元素、雜湊函數和謂詞,但使用分配器 a

並行性

other 上鎖定。


具備配置器的移動建構子
concurrent_node_set(concurrent_node_set&& other, Allocator const& a);

如果 a == other.get_allocator(),則 other 的元素會直接轉移到新表格;否則,元素會從 other 的元素移動建構而來。雜湊函式和述詞會從 other 移動建構而來,而配置器會從 a 複製建構而來。如果 啟用統計資訊,則當 a == other.get_allocator() 時,會轉移來自 other 的內部統計資訊,並總是呼叫 other.reset_stats()

並行性

other 上鎖定。


從 unordered_node_set 移動建構函式
concurrent_node_set(unordered_node_set<Key, Hash, Pred, Allocator>&& other);

unordered_node_set 移動建構。other 的內部 bucket 陣列會直接轉移到新容器。雜湊函式、述詞和配置器會從 other 移動建構而來。如果 啟用統計資訊,則會轉移來自 other 的內部統計資訊,並呼叫 other.reset_stats()

複雜度

O(bucket_count())


初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il,
                    size_type n = implementation-defined
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,eql 作為鍵相等謂詞,以及 a,並將來自 il 的元素插入其中。

需求

如果使用預設值,則 hasherkey_equalallocator_type 需要為預設可建構


具備配置器的儲存桶計數建構子
concurrent_node_set(size_type n, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備雜湊函數和配置器的儲存桶計數建構子
concurrent_node_set(size_type n, hasher const& hf, allocator_type const& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,預設鍵相等謂詞,以及 a 作為分配器。

後置條件

size() == 0

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
  concurrent_node_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

hasherkey_equal 需要是預設可建構的


具備儲存桶計數和雜湊函數的迭代器範圍建構子
    template<class InputIterator>
      concurrent_node_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                          const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 [f, l) 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, const allocator_type& a);

使用 a 以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數和配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 a 以及預設雜湊函數和鍵相等謂詞,並將來自 il 的元素插入其中。

需求

hasherkey_equal 需要是 預設可建構 (DefaultConstructible) 的。


具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
                    const allocator_type& a);

建構一個至少有 n 個儲存桶的空表格,使用 hf 作為雜湊函數,a 作為分配器,以及預設鍵相等謂詞,並將來自 il 的元素插入其中。

需求

key_equal 需要是 預設可建構 (DefaultConstructible) 的。


解構子

~concurrent_node_set();
注意

解構子會套用至每個元素,並釋放所有記憶體


賦值

複製賦值
concurrent_node_set& operator=(concurrent_node_set const& other);

賦值運算子。銷毀先前存在的元素,從 other 複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignmentAlloc::propagate_on_container_copy_assignment::valuetrue,則從 other 複製賦值配置器,最後插入 other 元素的副本。

需求

value_type可複製插入

並行性

阻塞於 *thisother


移動賦值
concurrent_node_set& operator=(concurrent_node_set&& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_move_assignment::value);

移動賦值運算子。會銷毀先前存在的元素,交換來自 other 的雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment 存在且 Alloc::propagate_on_container_move_assignment::valuetrue,則會從 other 移動賦值配置器。如果在這一點上配置器等於 other.get_allocator(),則 other 的內部 bucket 陣列會直接轉移到 *this;否則,會插入 other 元素的移動建構副本。如果 啟用統計資訊,則當最終配置器等於 other.get_allocator() 時,會轉移來自 other 的內部統計資訊,並總是呼叫 other.reset_stats()

並行性

阻塞於 *thisother


初始化列表賦值
concurrent_node_set& operator=(std::initializer_list<value_type> il);

從初始化列表中的值賦值。所有先前存在的元素都會被銷毀。

需求

value_type可複製插入

並行性

阻塞於 *this


訪問

[c]visit
template<class F> size_t visit(const key_type& k, F f);
template<class F> size_t visit(const key_type& k, F f) const;
template<class F> size_t cvisit(const key_type& k, F f) const;
template<class K, class F> size_t visit(const K& k, F f);
template<class K, class F> size_t visit(const K& k, F f) const;
template<class K, class F> size_t cvisit(const K& k, F f) const;

如果存在鍵等效於 k 的元素 x,則使用對 x 的常數參考調用 f

傳回

訪問的元素數 (0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。


批量訪問
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f);
template<class FwdIterator, class F>
  size_t visit(FwdIterator first, FwdIterator last, F f) const;
template<class FwdIterator, class F>
  size_t cvisit(FwdIterator first, FwdIterator last, F f) const;

對於範圍 [first, last) 中的每個元素 k,如果容器中存在鍵等效於 k 的元素 x,則使用對 x 的常數參考調用 f

儘管在功能上等同於個別調用每個鍵的 [c]visit,但由於內部的最佳化,批量訪問通常執行得更快。建議 std::distance(first,last) 至少為 bulk_visit_size 以享受效能提升:超過此大小,預計效能不會進一步提高。

需求

FwdIterator 是一個 LegacyForwardIterator (C++11 至 C++17),或滿足 std::forward_iterator (C++20 及更高版本)。對於 K = std::iterator_traits<FwdIterator>::value_typeK 要麼是 key_type,否則 Hash::is_transparentPred::is_transparent 是有效的成員 typedef。在後一種情況下,程式庫假設 Hash 可以使用 KKey 呼叫,並且 Pred 是透明的。這使得異質查閱能夠避免建立 Key 類型實例的成本。

傳回

訪問的元素數。


[c]visit_all
template<class F> size_t visit_all(F f);
template<class F> size_t visit_all(F f) const;
template<class F> size_t cvisit_all(F f) const;

使用對表格中每個元素的常數參考連續調用 f

傳回

訪問的元素數。


平行 [c]visit_all
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> void visit_all(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> void cvisit_all(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的常數參考調用 f。根據指定的執行策略的語義進行平行化執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。


[c]visit_while
template<class F> bool visit_while(F f);
template<class F> bool visit_while(F f) const;
template<class F> bool cvisit_while(F f) const;

使用對表格中每個元素的常數參考連續調用 f,直到 f 返回 false 或訪問完所有元素。

傳回

如果 f 曾經傳回 false,則為 false


平行 [c]visit_while
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f);
template<class ExecutionPolicy, class F> bool visit_while(ExecutionPolicy&& policy, F f) const;
template<class ExecutionPolicy, class F> bool cvisit_while(ExecutionPolicy&& policy, F f) const;

使用對表格中每個元素的常數參考調用 f,直到 f 返回 false 或訪問完所有元素。根據指定的執行策略的語義進行平行化執行。

傳回

如果 f 曾經傳回 false,則為 false

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,這些多載才會參與多載解析。

不允許未排序的執行策略。

平行化表示執行不一定在 f 傳回 false 後立即完成,因此,f 可能會使用傳回值也為 false 的其他元素呼叫。


大小和容量

empty
[[nodiscard]] bool empty() const noexcept;
傳回

size() == 0


size
size_type size() const noexcept;
傳回

表格中的元素數。

注意

在存在併發插入操作的情況下,傳回的值可能無法準確反映執行後表格的實際大小。


max_size
size_type max_size() const noexcept;
傳回

最大可能表格的 size()


修改器

emplace
template<class... Args> bool emplace(Args&&... args);

只有當表格中不存在具有等效鍵的元素時,才將使用引數 args 建構的物件插入表格中。

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


複製插入
bool insert(const value_type& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


移動插入
bool insert(value_type&& obj);

當且僅當表中沒有具有等效鍵的元素時,才將 obj 插入表中。

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


透明插入
template<class K> bool insert(K&& k);

如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k) 建構的元素。

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,此多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍
template<class InputIterator> size_type insert(InputIterator first, InputIterator last);

等同於

  while(first != last) this->emplace(*first++);
傳回

插入的元素數量。


插入初始化列表
size_type insert(std::initializer_list<value_type> il);

等同於

  this->insert(il.begin(), il.end());
傳回

插入的元素數量。


插入節點
insert_return_type insert(node_type&& nh);

如果 nh 不為空,則僅當表格中沒有與 nh.value() 等效的鍵的元素時,才會將相關元素插入表格。當函式返回時,nh 為空。

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果因呼叫 hasher 以外的操作而拋出例外,則函數不會產生任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


emplace_or_[c]visit
template<class... Args, class F> bool emplace_or_visit(Args&&... args, F&& f);
template<class... Args, class F> bool emplace_or_cvisit(Args&&... args, F&& f);

如果在表格中沒有具有等效鍵的元素,則在表格中插入使用參數 args 建構的物件。否則,使用對等效元素的常數參考調用 f

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f


複製 insert_or_[c]visit
template<class F> bool insert_or_visit(const value_type& obj, F f);
template<class F> bool insert_or_cvisit(const value_type& obj, F f);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj。否則,使用對等效元素的常數參考調用 f

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


移動 insert_or_[c]visit
template<class F> bool insert_or_visit(value_type&& obj, F f);
template<class F> bool insert_or_cvisit(value_type&& obj, F f);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj。否則,使用對等效元素的常數參考調用 f

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


透明 insert_or_[c]visit
template<class K, class F> bool insert_or_visit(K&& k, F f);
template<class K, class F> bool insert_or_cvisit(K&& k, F f);

當且僅當容器中沒有具有等效鍵的元素時,才在容器中插入從 std::forward<K>(k) 建構的元素。否則,使用對等效元素的常數參考調用 f

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,這些多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍或訪問
template<class InputIterator,class F>
    size_type insert_or_visit(InputIterator first, InputIterator last, F f);
template<class InputIterator,class F>
    size_type insert_or_cvisit(InputIterator first, InputIterator last, F f);

等同於

  while(first != last) this->emplace_or_[c]visit(*first++, f);
傳回

插入的元素數量。


插入初始化列表或訪問
template<class F> size_type insert_or_visit(std::initializer_list<value_type> il, F f);
template<class F> size_type insert_or_cvisit(std::initializer_list<value_type> il, F f);

等同於

  this->insert_or_[c]visit(il.begin(), il.end(), std::ref(f));
傳回

插入的元素數量。


插入節點或訪問
template<class F> insert_return_type insert_or_visit(node_type&& nh, F f);
template<class F> insert_return_type insert_or_cvisit(node_type&& nh, F f);

如果 nh 為空,則不執行任何操作。否則,僅當表格中沒有與 nh.value() 等效的鍵的元素時,才會將相關元素插入表格。否則,會使用對等元素的 const 參考來調用 f

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果除了呼叫 hasher 或呼叫 f 之外的操作擲回例外,則函式沒有任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


emplace_and_[c]visit
template<class... Args, class F1, class F2>
  bool emplace_or_visit(Args&&... args, F1&& f1, F2&& f2);
template<class... Args, class F1, class F2>
  bool emplace_or_cvisit(Args&&... args, F1&& f1, F2&& f2);

如果在表格中沒有具有等效鍵的元素,則在表格中插入使用參數 args 建構的物件,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 可從 args 建構。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 f1f2


複製 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(const value_type& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(const value_type& obj, F1 f2, F2 f2);

僅當表格中沒有具有等效鍵的元素時,才將 obj 插入表格,然後使用對新建立元素的 const 參考來調用 f1。否則,會使用對等元素的 const 參考來調用 f

需求

value_type 是可複製插入 (CopyInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


移動 insert_and_[c]visit
template<class F1, class F2> bool insert_and_visit(value_type&& obj, F1 f1, F2 f2);
template<class F1, class F2> bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2);

當且僅當表格中沒有具有等效鍵的元素時,才在表格中插入 obj,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 是可移動插入 (MoveInsertable) 的。

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。


透明 insert_and_[c]visit
template<class K, class F1, class F2> bool insert_and_visit(K&& k, F1 f1, F2 f2);
template<class K, class F1, class F2> bool insert_and_cvisit(K&& k, F1 f1, F2 f2);

當且僅當容器中沒有具有等效鍵的元素時,才在容器中插入從 std::forward<K>(k) 建構的元素,然後使用對新建立的元素的常數參考調用 f1。否則,使用對等效元素的常數參考調用 f2

需求

value_type 可透過 k 進行就地建構 (EmplaceConstructible)

傳回

如果進行了插入,則為 true

並行性

*this 上進行重新雜湊時會封鎖。

注意

僅當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,這些多載才會參與多載解析。該程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這允許異質查找,從而避免了實例化 Key 類型實例的成本。


插入迭代器範圍和訪問
template<class InputIterator,class F1, class F2>
    size_type insert_and_visit(InputIterator first, InputIterator last, F1 f1, F2 f2);
template<class InputIterator,class F1, class f2>
    size_type insert_and_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2);

等同於

  while(first != last) this->emplace_and_[c]visit(*first++, f1, f2);
傳回

插入的元素數量。


插入初始化列表和訪問
template<class F1, class F2>
  size_type insert_and_visit(std::initializer_list<value_type> il, F1 f1, F2 f2);
template<class F1, class F2>
  size_type insert_and_cvisit(std::initializer_list<value_type> il, F1 f1, F2 f2);

等同於

  this->insert_and_[c]visit(il.begin(), il.end(), std::ref(f1), std::ref(f2));
傳回

插入的元素數量。


插入節點並訪問
template<class F1, class F2>
  insert_return_type insert_and_visit(node_type&& nh, F1 f1, F2 f2);
template<class F1, class F2>
  insert_return_type insert_and_cvisit(node_type&& nh, F1 f1, F2 f2);

如果 nh 為空,則不執行任何操作。否則,僅當表格中沒有與 nh.value() 等效的鍵的元素時,才會將相關元素插入表格,然後使用對新插入元素的 const 參考來調用 f1。否則,會使用對等元素的 const 參考來調用 f2

傳回

insertednode 建構的 insert_return_type 物件

  • 如果 nh 為空,則 insertedfalsenode 為空。

  • 否則,如果插入成功,則 inserted 為 true 且 node 為空。

  • 如果插入失敗,則 inserted 為 false 且 node 具有 nh 的先前值。

拋出

如果除了呼叫 hasher 或呼叫 f1f2 之外的操作擲回例外,則函式沒有任何作用。

並行性

*this 上進行重新雜湊時會封鎖。

注意

如果 nh 不為空,且 nh 和容器的配置器不相等,則行為未定義。


erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);

如果存在具有與 k 等效鍵的元素,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


依鍵刪除_if
template<class F> size_type erase_if(const key_type& k, F f);
template<class K, class F> size_type erase_if(const K& k, F f);

如果存在具有與 k 等效鍵的元素 x,且 f(x)true,則將其刪除。

傳回

刪除的元素數量(0 或 1)。

拋出

只有當 hasherkey_equalf 擲回例外時,才會擲回例外。

注意

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>false 時,template<class K, class F> 多載才會參與多載解析。

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K, class F> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,並且 Pred 是透明的。這可啟用異質查閱,從而避免了實例化 Key 類型實例的成本。


erase_if
template<class F> size_type erase_if(F f);

使用表格中每個元素的參考來連續調用 f,並刪除 f 返回 true 的元素。

傳回

已刪除的元素數量。

拋出

只有當 f 擲回例外時,才會擲回例外。


平行刪除_if
template<class ExecutionPolicy, class  F> void erase_if(ExecutionPolicy&& policy, F f);

使用表格中每個元素的參考來調用 f,並刪除 f 返回 true 的元素。根據指定的執行原則語意來平行處理執行。

拋出

根據所使用執行策略的例外處理機制,如果 f 內擲回例外,可能會呼叫 std::terminate

注意

僅在支援 C++17 平行演算法的編譯器中可用。

只有當 std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true 時,此多載才會參與多載解析。

不允許未排序的執行策略。


交換 (swap)
void swap(concurrent_node_set& other)
  noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
           boost::allocator_traits<Allocator>::propagate_on_container_swap::value);

將表格內容與參數交換。

如果宣告了 Allocator::propagate_on_container_swapAllocator::propagate_on_container_swap::valuetrue,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。

拋出

除非 key_equalhasher 在交換時擲回例外,否則無任何作用。

並行性

阻塞於 *thisother


提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);

提取具有與 k 等效鍵的元素(如果存在)。

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅在 hasherkey_equal 拋出例外時才會拋出例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


extract_if
template<class F> node_type extract_if(const key_type& k, F f);
template<class K, class F> node_type extract_if(K&& k, F f);

如果存在且 f(x)true,則會提取具有與 k 等效的鍵的元素 x

傳回

一個包含提取元素的 node_type 物件,如果未提取任何元素,則為空。

拋出

僅當 hasherkey_equalf 擲回例外時才會擲回例外。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。


清除 (clear)
void clear() noexcept;

刪除表格中的所有元素。

後置條件

size() == 0max_load() >= max_load_factor() * bucket_count()

並行性

阻塞於 *this


合併 (merge)
template<class H2, class P2>
  size_type merge(concurrent_node_set<Key, H2, P2, Allocator>& source);
template<class H2, class P2>
  size_type merge(concurrent_node_set<Key, H2, P2, Allocator>&& source);

source 中鍵值尚未存在於 *this 的所有元素移動插入,並從 source 中刪除它們。

傳回

插入的元素數量。

並行性

*thissource 上封鎖。


觀察器

get_allocator
allocator_type get_allocator() const noexcept;
傳回

表格的配置器。


hash_function
hasher hash_function() const;
傳回

表格的雜湊函式。


key_eq
key_equal key_eq() const;
傳回

表格的鍵相等謂詞。


Set 操作

計數 (count)
size_type        count(const key_type& k) const;
template<class K>
  size_type      count(const K& k) const;
傳回

具有與 k 等效鍵的元素數量(0 或 1)。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


包含 (contains)
bool             contains(const key_type& k) const;
template<class K>
  bool           contains(const K& k) const;
傳回

一個布林值,指示表格中是否存在鍵等於 k 的元素。

注意

只有當 Hash::is_transparentPred::is_transparent 是有效的成員 typedef 時,template<class K> 多載才會參與多載解析。程式庫假設 Hash 可使用 KKey 呼叫,且 Pred 是透明的。這能夠進行異質查閱,避免了實例化 Key 類型實例的成本。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


桶子介面

bucket_count
size_type bucket_count() const noexcept;
傳回

儲存桶陣列的大小。


雜湊策略

載入因子 (load_factor)
float load_factor() const noexcept;
傳回

static_cast<float>(size())/static_cast<float>(bucket_count()),如果 bucket_count() == 0,則為 0


最大載入因子 (max_load_factor)
float max_load_factor() const noexcept;
傳回

傳回表格的最大負載因子。


設定最大載入因子
void max_load_factor(float z);
作用

不執行任何操作,因為不允許使用者變更此參數。保留此參數是為了與 boost::unordered_set 相容。


max_load
size_type max_load() const noexcept;
傳回

在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。

注意

建構、重新雜湊或清除後,表格的最大負載至少為 max_load_factor() * bucket_count()。在高負載條件下刪除時,此數目可能會減少。

在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。


重新雜湊 (rehash)
void rehash(size_type n);

如有必要,變更儲存桶陣列的大小,使其至少有 n 個儲存桶,且負載因子小於或等於最大負載因子。在適用的情況下,這會擴大或縮小與表格相關聯的 bucket_count()

size() == 0 時,rehash(0) 會解除配置底層儲存桶陣列。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


保留 (reserve)
void reserve(size_type n);

等同於 a.rehash(ceil(n / a.max_load_factor()))

rehash 類似,此函式可用於擴大或縮小表格中的儲存桶數目。

拋出

如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。

並行性

阻塞於 *this


統計

get_stats
stats get_stats() const;
傳回

到目前為止表格執行的插入和查閱操作的統計說明。

注意

僅當 啟用統計資訊計算時才可用。


reset_stats
void reset_stats() noexcept;
作用

將表格保留的內部統計資料設定為零。

注意

僅當 啟用統計資訊計算時才可用。


推導指引

如果符合下列任何一項,則推導指南不會參與多載解析

  • 它具有 InputIterator 樣板參數,且推導出的類型不符合輸入迭代器的資格。

  • 它具有 Allocator 樣板參數,且推導出的類型不符合配置器的資格。

  • 它具有 Hash 樣板參數,且推導出的類型是整數類型或是符合配置器資格的類型。

  • 它具有 Pred 樣板參數,且推導出的類型符合配置器的資格。

推導指南中的 size_type 參數類型指的是由推導指南推導出的容器類型的 size_type 成員類型。其預設值與所選建構函式的預設值一致。

iter-value-type
template<class InputIterator>
  using iter-value-type =
    typename std::iterator_traits<InputIterator>::value_type; // exposition only

相等比較

operator==
template<class Key, class Hash, class Pred, class Alloc>
  bool operator==(const concurrent_node_set<Key, Hash, Pred, Alloc>& x,
                  const concurrent_node_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 true

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


operator!=
template<class Key, class Hash, class Pred, class Alloc>
  bool operator!=(const concurrent_node_set<Key, Hash, Pred, Alloc>& x,
                  const concurrent_node_set<Key, Hash, Pred, Alloc>& y);

如果 x.size() == y.size() 且對於 x 中的每個元素,y 中都有一個具有相同鍵的元素,且值相等(使用 operator== 來比較值類型),則返回 false

並行性

xy 上封鎖。

注意

如果兩個表格沒有等效的相等謂詞,則行為未定義。


交換

template<class Key, class Hash, class Pred, class Alloc>
  void swap(concurrent_node_set<Key, Hash, Pred, Alloc>& x,
            concurrent_node_set<Key, Hash, Pred, Alloc>& y)
    noexcept(noexcept(x.swap(y)));

等同於

x.swap(y);

erase_if

template<class K, class H, class P, class A, class Predicate>
  typename concurrent_node_set<K, H, P, A>::size_type
    erase_if(concurrent_node_set<K, H, P, A>& c, Predicate pred);

等同於

c.erase_if(pred);

序列化

可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 concurrent_node_set。支援一般封存和 XML 封存。

將 concurrent_node_set 儲存到封存

concurrent_node_set x 的所有元素儲存到封存 (XML 封存) ar

需求

value_type 是可序列化的 (XML 可序列化的),並且它支援 Boost.Serialization save_construct_data/load_construct_data 協定 (由 預設可建構 (DefaultConstructible) 類型自動支援)。

並行性

x 上封鎖。


從封存載入 concurrent_node_set

刪除 concurrent_node_set x 的所有先前存在的元素,並從封存 (XML 封存) ar 插入已還原的原始 concurrent_node_set other 的元素副本,這些副本已儲存到 ar 讀取的儲存空間。

需求

x.key_equal() 在功能上等同於 other.key_equal()

並行性

x 上封鎖。

變更日誌

版本 1.87.0 - 重大更新

  • 新增了並行、基於節點的容器 boost::concurrent_node_mapboost::concurrent_node_set

  • 新增了 insert_and_visit(x, f1, f2) 以及類似的並行容器操作,它們允許在插入後立即訪問元素 (相反,insert_or_visit(x, f) 僅在插入元素時才會訪問元素)。

  • 在某些 boost::concurrent_flat_set 操作中,使訪問採用獨佔鎖定,以允許安全地修改元素 (PR#265)。

  • 在 Visual Studio Natvis 中,支援使用花式指標的任何配置器容器。這適用於任何花式指標類型,只要針對該花式指標類型編寫適當的 Natvis 自訂點「Intrinsic」函數即可。

  • 為所有容器和迭代器新增了 GDB 美化輸出器。對於使用花式指標的配置器容器,只有在為花式指標類型本身編寫適當的美化輸出器時,這些輸出器才能正常運作。

  • 修正了開放定址容器的 std::initializer_list 指派問題 (PR#277)。

  • 允許將不可複製的可呼叫物件傳遞給並行容器的 insert_{and|or}_[c]visitstd::initializer_list 多載,方法是在內部將可呼叫物件的 std::reference_wrapper 傳遞給迭代器對多載。

版本 1.86.0

  • 當標頭 <memory_resource> 可用時,新增了容器的 pmr 別名。別名 boost::unordered::pmr::[container] 指的是具有 std::pmr::polymorphic_allocator 配置器類型的 boost::unordered::[container]

  • 使開放定址和並行容器能夠在內部計算並提供受雜湊函數品質影響的統計指標。此功能由全域巨集 BOOST_UNORDERED_ENABLE_STATS 啟用。

  • 雪崩雜湊函數現在必須透過嵌入式 value 常數設定為 trueis_avalanching typedef 標記(通常,將 is_avalanching 定義為 std::true_type)。using is_avalanching = void 已被棄用,但為了向後相容性而允許使用。

  • 為容器和迭代器新增了 Visual Studio Natvis 框架自訂視覺化。這適用於所有使用原始指標的配置器容器。在此版本中,如果容器的配置器使用花式指標,則不支援這些容器和迭代器。這可能會在後續版本中解決。

版本 1.85.0

  • 最佳化了針對 value_typeinit_type(如果適用)參數的 emplace(),以繞過建立中間物件。該參數已經與原本的中間物件類型相同。

  • 最佳化了 map 容器上針對 k,v 參數的 emplace(),以延遲建構物件,直到確定應該插入元素為止。當 map 的 key_type 可移動建構時,或當 k 參數為 key_type 時,會發生此最佳化。

  • 修正了具有 explicit 複製建構子的配置器的支援問題 (PR#234)。

  • 修正了 unordered_multimap::find(k, hash, eq)const 版本中的錯誤 (PR#238)。

版本 1.84.0 - 重大更新

  • 新增了 boost::concurrent_flat_set

  • 為並行容器新增了 [c]visit_while 操作,具有序列和並行變體。

  • 新增了從 boost::concurrent_flat_(map|set)boost::unordered_flat_(map|set) 的高效移動建構,反之亦然。

  • 為並行容器新增了批量訪問,以提高查找效能。

  • 新增了偵測使用者程式碼非法重新進入並行容器的偵錯模式機制。

  • 為所有容器及其(非本地)迭代器類型新增了 Boost.Serialization 支援。

  • 新增了對開放定址和並行容器的花式指標支援。這使得在共享記憶體中建構容器的 Boost.Interprocess 配置器等情境成為可能。

  • 修正了封閉定址容器的本地迭代器的指標運算子成員中的錯誤 (PR#221,感謝 GitHub 使用者 vslashg 發現並修復此問題)。

  • 從此版本開始,boost::unordered_[multi]setboost::unordered_[multi]map 僅適用於 C++11 及更高版本。

版本 1.83.0 - 重大更新

  • 新增了 boost::concurrent_flat_map,這是一個基於開放定址的快速、執行緒安全的雜湊映射。

  • 加快了開放定址容器的迭代速度。

  • 在開放定址容器中,先前不傳回任何內容的 erase(iterator) 現在傳回一個可轉換為下一個元素的迭代器的代理物件。這使得典型的 it = c.erase(it) 慣用語成為可能,而當不使用傳回的代理時,不會產生任何效能損失。

版本 1.82.0 - 重大更新

  • 計劃棄用 C++03 支援。Boost 1.84.0 將不再支援 C++03 模式,而 C++11 將成為使用該程式庫的新最低要求。

  • 新增了基於節點的開放定址容器 boost::unordered_node_mapboost::unordered_node_set

  • 依照 P2363 中指定,將異質查找擴展到更多成員函數。

  • 將開放定址容器的先前後混合處理替換為基於常數擴展乘法的新演算法。

  • 修正了內部 emplace() 實作中的錯誤,其中堆疊本地類型未使用容器的配置器正確建構,這會破壞 uses-allocator 建構。

版本 1.81.0 - 重大更新

  • 新增了基於開放定址的快速容器 boost::unordered_flat_mapboost::unordered_flat_set

  • 為所有容器新增了 CTAD 推導指南。

  • 新增了 LWG 問題 2713 中指定的遺失建構子。

版本 1.80.0 - 重大更新

  • 重構內部實作以大幅提高速度

  • 允許 final Hasher 和 KeyEqual 物件

  • 更新文件,新增基準圖表和關於新內部資料結構的註解

版本 1.79.0

  • 改進了 C++20 支援

    • 所有容器都已更新以支援異質 countequal_rangefind

    • 所有容器現在都實作了成員函數 contains

    • 已為所有容器實作 erase_if

  • 改進了 C++23 支援

    • 所有容器都已更新以支援異質 eraseextract

  • reserve 的行為變更為預先配置 (PR#59)。

  • 測試套件中的各種警告修正。

  • 更新程式碼以在內部使用 boost::allocator_traits

  • 切換到費波那契雜湊。

  • 更新文件,以 AsciiDoc 而非 QuickBook 撰寫。

版本 1.67.0

  • 改進了 C++17 支援

    • 從標準新增範本推導指南。

    • 在節點控制代碼中使用 optional 的簡單實作,使其更接近標準。

    • 將遺失的 noexcept 規範新增至 swapoperator= 和節點控制代碼,並變更實作以符合。在實作中使用 std::allocator_traits::is_always_equal,或在不可用時使用我們自己的實作,以及 boost::is_nothrow_swappable

  • 改進了 C++20 支援

    • 使用具有建議的 C++20 語意的 boost::to_address,而不是舊的自訂實作。

  • element_type 新增至迭代器,以便 std::pointer_traits 可以正常運作。

  • 在 Visual C++ 的最新版本以及 Dinkumware 標準程式庫的其他用途中使用 std::piecewise_construct,現在使用 Boost.Predef 來檢查編譯器和程式庫版本。

  • 使用 std::iterator_traits 而不是 boost 迭代器特性,以移除對 Boost.Iterator 的依賴。

  • 移除迭代器從 std::iterator 的繼承,這在 C++17 中已棄用,感謝 Daniela Engert (PR#7)。

  • 停止使用 BOOST_DEDUCED_TYPENAME

  • 更新一些 Boost include 路徑。

  • 重新命名一些內部方法和變數。

  • 各種測試改進。

  • 其他內部變更。

版本 1.66.0

  • 更簡單的移動建構實作。

  • 文件修正 (GitHub #6)。

版本 1.65.0

  • 將已棄用的屬性新增至 quick_eraseerase_return_void。這次我真的會在未來的版本中移除它們。

  • 小標準合規性修正

    • swap 自由函數的 noexpect 規格。

    • 新增遺失的 insert(P&&) 方法。

版本 1.64.0

  • unordered_map 中初步支援新的 C++17 成員函數:insert_or_assigntry_emplace

  • 初步支援 mergeextract。尚不包括在 unordered_mapunordered_multimap 之間或在 unordered_setunordered_multiset 之間傳輸節點。這有望在下一個 Boost 版本中實現。

版本 1.63.0

  • 檢查 insert/emplace_hint 中的提示迭代器。

  • 修正一些警告,主要是在測試中。

  • 手動寫出少數參數的 emplace_args - 應該使範本錯誤訊息更容易理解。

  • 移除 emplace 引數中多餘的 boost::forward 使用,這修正了在舊版 Visual C++ 中插入字串常值的問題。

  • 修正了指派中的異常安全問題。如果 bucket 配置擲回異常,它可能會覆寫雜湊和相等函數,同時將現有元素保留在原處。這意味著函數物件將與容器元素不符,因此元素可能位於錯誤的 bucket 中,並且等效元素會被錯誤地處理。

  • 各種參考文件改進。

  • 更好的配置器支援 (#12459)。

  • 使無引數建構子成為隱含的。

  • 實作遺失的配置器感知建構子。

  • 修正空容器的雜湊/鍵相等函數的指派。

  • 從文件範例中移除 unary/binary_function。它們已在 C++17 中移除。

  • 支援 emplace 中的 10 個建構子引數。它本應支援最多 10 個引數,但前處理器程式碼中的一個差一錯誤意味著它僅支援最多 9 個引數。

版本 1.62.0

  • 移除已棄用的 boost::iterator 的使用。

  • 移除 BOOST_NO_STD_DISTANCE 解決方案。

  • 移除 BOOST_UNORDERED_DEPRECATED_EQUALITY 警告。

  • 更簡單的指派實作,修正了 unordered_multisetunordered_multimap 的異常安全問題。可能會稍微慢一點。

  • 停止使用一些舊編譯器有問題的傳回值 SFINAE。

版本 1.58.0

  • 從 const 迭代器中移除不必要的範本參數。

  • 重新命名一些迭代器類別中的私有 iterator typedef,因為它會混淆某些特性類別。

  • 修正具有有狀態、propagate_on_container_move_assign 配置器的移動指派 (#10777)。

  • 修正移動指派中罕見的異常安全問題。

  • 修正計算要配置的 bucket 數時可能發生的溢位 (GitHub #4)。

版本 1.57.0

  • 修正迭代器中的 pointer typedef (#10672)。

  • 修正 Coverity 警告 (GitHub #2)。

版本 1.56.0

  • 修正一些陰影變數警告 (#9377)。

  • 修正文件中的配置器使用 (#9719)。

  • 始終為整數使用質數 bucket 數。修正了插入連續整數時的效能迴歸,儘管這會使其他用途變慢 (#9282)。

  • 僅使用配置器建構元素,如 C++11 標準中所述。

版本 1.55.0

  • 避免一些警告 (#8851, #8874)。

  • 避免透過迭代器上的 ADL 公開一些詳細函數。

  • 遵循標準,僅使用配置器的建構和銷毀方法來建構和銷毀儲存的元素。不要將它們用於內部資料,如指標。

版本 1.54.0

  • 將標準中指定的方法標記為 noexpect。更多內容將在下一個版本中推出。

  • 如果已知雜湊函數和相等述詞都具有 nothrow 移動指派或建構,則使用它們。

版本 1.53.0

  • 移除對舊的預標準可變參數對建構子和相等實作的支援。兩者自 Boost 1.48 以來都已棄用。

  • 移除對已棄用的組態巨集的使用。

  • 更多內部實作變更,包括更簡單的 erase 實作。

版本 1.52.0

  • 更快的指派,它會在可能的情況下指派給現有節點,而不是建立全新的節點和複製建構。

  • 修正了 erase_range 中的錯誤 (#7471)。

  • 還原了一些關於節點建立方式的內部變更,特別是對於 C++11 編譯器。'construct' 和 'destroy' 對於 C++11 配置器應該會更好地運作。

  • 簡化了一些實作。希望更強健。

版本 1.51.0

  • 修正了當將 C++11 編譯器與 C++03 配置器一起使用時的建構/銷毀問題 (#7100)。

  • 移除 try..catch 以支援在沒有例外的情況下編譯。

  • 調整 SFINAE 的使用以嘗試支援 g++ 3.4 (#7175)。

  • 已更新為使用新的組態巨集。

版本 1.50.0

  • 修正 unordered_multisetunordered_multimap 的相等性比較。

  • 工單 6857:實作 reserve

  • 工單 6771:避免 gcc 的 -Wfloat-equal 警告。

  • 工單 6784:修正一些 Sun 專屬的程式碼。

  • 工單 6190:避免 gcc 的 -Wshadow 警告。

  • 工單 6905:使巨集中的命名空間與 bcp 自訂命名空間相容。由 Luke Elliott 修正。

  • 移除一些較小的質數桶數量,因為它們可能會導致碰撞機率較高(例如,5 的倍數非常常見,因為我們使用 10 進位)。

  • 在舊版本的 Visual C++ 上,使用容器庫的 allocator_traits 實作,因為它更可能正常運作。

  • 在具有 64 位元 std::size_t 的機器上,使用 2 的冪次方的桶數量,並使用 Thomas Wang 的雜湊函數來選擇要使用哪個桶。因為對於 64 位元值來說,取模運算非常慢。

  • 一些內部變更。

版本 1.49.0

  • 修正因意外的奇數賦值造成的警告。

  • 稍微改善的錯誤訊息。

版本 1.48.0 - 重大更新

這是一項重大變更,已轉換為使用 Boost.Move 的移動模擬,並更符合 C++11 標準。詳細資訊請參閱符合性章節

此容器現在符合 C++11 的複雜度要求,但為此需使用稍微多一點的記憶體。這表示不再需要 quick_eraseerase_return_void,它們將在未來的版本中移除。

C++11 的支援導致了一些破壞性變更

  • 相等性比較已變更為 C++11 規格。在具有相等鍵的容器中,過去具有相等鍵的群組中的元素必須具有相同的順序才能被視為相等,現在它們可以是彼此的排列組合。若要使用舊的行為,請定義巨集 BOOST_UNORDERED_DEPRECATED_EQUALITY

  • 當要交換的兩個容器具有不相等的配置器時,swap 的行為會有所不同。它過去會使用適當的配置器來配置新的節點,現在如果配置器具有成員結構 propagate_on_container_swap,使得 propagate_on_container_swap::value 為 true,它會交換配置器。

  • 配置器的 constructdestroy 函式會使用原始指標呼叫,而不是配置器的 pointer 類型。

  • emplace 過去會模擬早期 C++0x 草稿中出現的可變參數 pair 建構函式。由於它們已被移除,因此不再這樣做。它確實會模擬新的 piecewise_construct pair 建構函式 - 只是您需要使用 boost::piecewise_construct。若要使用舊的可變參數建構函式模擬,請定義 BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT

版本 1.45.0

  • 修正使用傳回複製 value_type 的迭代器插入 unordered_mapunordered_set 時的錯誤。

版本 1.43.0

  • 工單 3966erase_return_void 現在是 quick_erase,這是目前解決迭代器刪除速度慢問題的先驅,儘管這在未來很有可能會變更。舊的方法名稱仍保留以確保向後相容性,但被視為已棄用,並將在未來的版本中移除。

  • 使用 Boost.Exception。

  • 停止使用已棄用的 BOOST_HAS_* 巨集。

版本 1.42.0

  • 支援使用不完整的 value 類型來實例化容器。

  • 減少警告數量(主要在測試中)。

  • 改善 codegear 相容性。

  • 工單 3693:新增 erase_return_void 作為目前 erase 的臨時解決方案,它可能效率不佳,因為它必須找到下一個元素才能傳回迭代器。

  • 為相容的鍵新增範本化的 find 多載。

  • 工單 3773:為 ptrdiff_t 新增遺失的 std 限定詞。

  • 一些程式碼格式變更,使幾乎所有程式碼行都符合 80 個字元。

版本 1.41.0 - 重大更新

  • 原始版本大量使用巨集來規避一些舊編譯器對範本支援不佳的問題。但由於我不再支援這些編譯器,且巨集的使用開始成為維護負擔,因此已將其實作類別重寫為使用範本而非巨集。

  • 由於使用 boost::compressed_pair 進行 EBO 和略有不同的函式緩衝區(現在使用布林值而不是成員指標),因此容器物件現在更小。

  • 桶是延遲配置的,這表示建構一個空容器不會配置任何記憶體。

版本 1.40.0

  • 工單 2975:將質數清單儲存為前處理器序列 - 如此一來,如果未來再次變更,它將始終獲得正確的長度。

  • 工單 1978:為所有編譯器實作 emplace

  • 工單 2908工單 3096:針對舊版本 borland 的一些解決方案,包括為所有容器新增顯式解構函式。

  • 工單 3082:停用不正確的 Visual C++ 警告。

  • 當標頭不可用時,針對 C++0x 功能的更佳組態。

  • 預設建立較少的桶。

版本 1.39.0

  • 工單 2756:避免 Visual C++ 2009 上的警告。

  • 一些其他對實作、測試和文件進行的次要內部變更。

  • 避免在 operator[] 中不必要的複製。

  • 工單 2975:修正質數清單的長度。

版本 1.38.0

  • 使用 boost::swap

  • 工單 2237:說明如果兩個物件的相等性述詞不相等,則它們的相等和不相等運算子是未定義的。感謝 Daniel Krügler。

  • 工單 1710:使用更大的質數清單。感謝 Thorsten Ottosen 和 Hervé Brönnimann。

  • 使用對齊的儲存體來儲存類型。這變更了配置器用於建構節點的方式。它過去會使用兩次對配置器的 construct 方法的呼叫來建構節點 - 一次用於指標,一次用於值。它現在會使用單次對 construct 的呼叫來建構節點,然後使用原地建構來建構值。

  • 在可用的情況下(目前僅限 C++0x 模式下的 g++ 4.4),新增對 C++0x 初始化列表的支援。

版本 1.37.0

  • 將帶提示的 emplace 多載重新命名為 emplace_hint,如n2691 中所述。

  • <boost/unordered/unordered_map_fwd.hpp><boost/unordered/unordered_set_fwd.hpp> 提供轉發標頭。

  • 將所有實作移至 boost/unordered 內部,以協助模組化,並希望使其更容易追蹤 Release 版本控制。

版本 1.36.0

第一個正式發行版。

  • 重新排列內部結構。

  • 移動語義 - 當 rvalue 參考可用時提供完整支援,當 rvalue 參考不可用時,使用精簡版的 Adobe 移動程式庫進行模擬。

  • 當 rvalue 參考和可變參數範本可用時提供 Emplace 支援。

  • 當 rvalue 參考和可變參數範本可用時,提供更有效率的節點配置。

  • 新增相等運算子。

Boost 1.35.0 附加元件 - 2008 年 3 月 31 日

非官方發行版已上傳至保管庫,以與 Boost 1.35.0 一起使用。納入了許多審查意見。

  • 由於 Boost 回歸測試,提高了可移植性。

  • 修正文件中的許多拼字錯誤和更清晰的文字。

  • 修正從最大載入因子計算大小時浮點數到 std::size_t 的轉換,並在計算中使用 double 以提高準確性。

  • 修正範例中的一些錯誤。

審閱版本

初始審查版本,用於 2007 年 12 月 7 日至 2007 年 12 月 16 日進行的審查。

參考文獻

Daniel James

Copyright © 2003, 2004 Jeremy B. Maitin-Shepard

Copyright © 2005-2008 Daniel James

Copyright © 2022-2023 Christian Mazakas

Copyright © 2022-2024 Joaquín M López Muñoz

Copyright © 2022-2023 Peter Dimov

Copyright © 2024 Braden Ganetsky

根據 Boost 軟體授權條款 1.0 版發行。(請參閱隨附的檔案 LICENSE_1_0.txt 或複製自 https://boost.dev.org.tw/LICENSE_1_0.txt)