簡介
雜湊表是一種非常流行的電腦資料結構,幾乎可以在任何程式語言中以某種形式找到。其他關聯式結構,例如 rb 樹(C++ 中由 std::set
和 std::map
使用)在插入和查找方面具有對數時間複雜度,而雜湊表(如果配置得當)平均以常數時間執行這些操作,並且通常快得多。
C++ 在 C++11 中引入了無序關聯式容器 std::unordered_set
、std::unordered_map
、std::unordered_multiset
和 std::unordered_multimap
,但自那時以來,對雜湊表的研究並未停止:CPU 架構的進步,例如更強大的快取、SIMD 操作和日益普及的 多核心處理器,為改進的基於雜湊的資料結構和 2011 年指定的無序關聯式容器無法達到的新用例開闢了可能性。
Boost.Unordered 提供了一個雜湊容器的目錄,具有不同的標準相容性層級、效能和預期的使用場景
基於節點 |
平坦 |
|
---|---|---|
封閉定址 |
|
|
開放定址 |
|
|
並行 |
|
|
-
封閉定址容器 完全符合 C++ 無序關聯式容器的規範,並在所需標準介面所施加的技術限制內,具有市場上最快的實作之一。
-
開放定址容器 依賴於快得多的資料結構和演算法(在典型情境下快 2 倍以上),同時略微偏離標準介面以適應實作。 有兩種變體:平坦式(最快)和基於節點式,後者在重新雜湊時提供指標穩定性,但代價是速度較慢。
-
最後,並行容器 的設計和實作旨在用於高效能多執行緒情境。 其介面與一般 C++ 容器的介面截然不同。 提供平坦式和基於節點的變體。
Boost.Unordered 中的所有 set 和 map 的實例化方式分別與 std::unordered_set
和 std::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 個元素 A
、B
、C
、D
和 E
的 7 個桶子的 boost::unordered_set
(這只是為了說明,容器通常會有更多桶子)。

為了決定將元素放置在哪個桶子中,容器將雜湊函數 Hash
應用於元素的鍵(對於 set,鍵是整個元素,但稱為鍵,以便將相同的術語用於 set 和 map)。 這會傳回 std::size_t
型別的值。 std::size_t
的值範圍遠大於桶子的數量,因此容器會對該值應用另一個轉換,以選擇將元素放置在其中的桶子。
擷取給定鍵的元素很簡單。 將相同的程序應用於鍵以找到正確的桶子。 然後將鍵與桶子中的元素進行比較,以找到任何符合的元素(使用相等謂詞 Pred
)。 如果雜湊函數運作良好,則元素將均勻分佈在各個桶子之間,因此只需要檢查少量元素。
在下一個章節中,有更多關於雜湊函數和相等謂詞的資訊。
您可以在圖表中看到 A
和 D
已放置在同一個桶子中。 當在此桶子中尋找元素時,最多進行 2 次比較,使得搜尋速度較慢。 這稱為碰撞。 為了保持快速,我們嘗試將碰撞降至最低。
如果我們改為使用 boost::unordered_flat_set
,而不是 boost::unordered_set
,則圖表如下所示

在開放定址容器中,桶子最多可以容納一個元素;如果發生碰撞(例如範例中的 D
),則該元素會使用原始位置附近的某個其他可用桶子。 鑑於這種更簡單的情境,Boost.Unordered 開放定址容器提供了一個非常有限的 API 來存取桶子。
所有容器 |
|
---|---|
方法 |
描述 |
|
桶子的數量。 |
僅限封閉定址容器 |
|
方法 |
描述 |
|
桶子數量的上限。 |
|
桶子 |
|
傳回將包含 |
|
傳回桶子 |
|
|
|
|
|
|
|
|
|
控制桶子的數量
當更多元素加入到無序關聯容器時,碰撞次數會增加,導致效能下降。為了避免這種情況,容器會在插入元素時增加儲存桶(bucket)的數量。您也可以透過呼叫 rehash
來告知容器變更儲存桶的數量(如果需要)。
標準規範給予實作者很大的自由度來決定如何選擇儲存桶的數量,但它確實基於容器的負載因子(load factor)做了一些要求,負載因子是指元素數量除以儲存桶數量。容器也有一個最大負載因子(maximum load factor),它們應該盡量保持負載因子低於這個值。
您無法直接控制儲存桶的數量,但有兩種方法可以影響它:
-
在建構容器或呼叫
rehash
時,指定最少的儲存桶數量。 -
透過呼叫
max_load_factor
來建議最大負載因子。
max_load_factor
並不讓您自行設定最大負載因子,它只讓您提供一個提示。即便如此,標準實際上並不要求容器對這個值給予太多關注。唯一必須讓負載因子小於最大值的時機是在呼叫 rehash
之後。但大多數實作會嘗試保持元素數量低於最大負載因子,並將最大負載因子設定為與提示相同或接近的值——除非您的提示值過小或過大。
所有容器 |
|
---|---|
方法 |
描述 |
|
建構一個至少有 |
|
建構一個至少有 |
|
每個儲存桶的平均元素數量。 |
|
回傳目前的最大負載因子。 |
|
變更容器的最大負載因子,使用 |
|
變更儲存桶的數量,使其至少有 |
僅適用於開放定址和並行容器 |
|
方法 |
描述 |
|
回傳重新雜湊(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。
方法 | 描述 |
---|---|
|
回傳容器的雜湊函數。 |
|
回傳容器的鍵相等函數。 |
一般容器
Boost.Unordered 的閉合定址(closed-addressing)容器 (boost::unordered_set
、boost::unordered_map
、boost::unordered_multiset
和 boost::unordered_multimap
) 完全符合 C++ 針對無序關聯容器的規範,因此,對於那些知道如何使用 std::unordered_set
、std::unordered_map
等的人來說,它們在 Boost.Unordered 中的同名容器是可以直接替換的。開放定址容器 (boost::unordered_node_set
、boost::unordered_node_map
、boost::unordered_flat_set
和 boost::unordered_flat_map
) 的介面非常相似,但它們在專用的標準相容性章節中列出了一些細微的差異。
對於沒有使用雜湊容器經驗但熟悉一般關聯容器(std::set
、std::map
、std::multiset
和 std::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
還有其他差異,這些差異列在與關聯容器的比較章節中。
迭代器失效
除了 rehash
和 reserve
之外,未指定其他成員函數如何影響儲存桶的數量,儘管當插入導致容器負載大於允許的最大值時,insert
只能使迭代器失效。對於大多數實作來說,這表示 insert
只有在發生這種情況時才會變更儲存桶的數量。迭代器可能會因呼叫 insert
、rehash
和 reserve
而失效。
至於指標和參考,它們永遠不會對基於節點的容器(boost::unordered_[multi]set
、boost::unordered_[multi]map
、boost::unordered_node_set
、boost::unordered_node_map
)失效,但當為 boost::unordered_flat_set
和 boost::unordered_flat_map
發生重新雜湊時,它們將會失效:這是因為這些容器將元素直接儲存在它們的保存儲存桶中,因此在配置新的儲存桶陣列時,必須透過移動建構來傳輸元素。
以類似於對 vector
使用 reserve
的方式,在插入大量元素之前呼叫 reserve
可能是一個好主意。這會將昂貴的重新雜湊排除在外,並讓您儲存迭代器,並確保它們不會失效。如果要將 n
個元素插入容器 x
中,您可以先呼叫:
x.reserve(n);
- 注意
-
reserve(n)
為至少n
個元素保留空間,分配足夠的儲存桶,以便不超過最大負載因子。由於最大負載因子定義為元素數量除以可用儲存桶總數,因此此函數在邏輯上等同於:
x.rehash(std::ceil(n / x.max_load_factor()))
請參閱關於
rehash
函數的參考資料以取得更多詳細資訊。
與關聯式容器比較
關聯容器 | 無序關聯容器 |
---|---|
由排序關係 |
由函數物件 |
可以使用 |
可以使用 |
建構子具有比較物件的可選額外參數。 |
建構子具有初始最小儲存桶數量、雜湊函數和相等物件的可選額外參數。 |
如果 |
如果 |
成員函數 |
沒有等效的成員函數。由於元素沒有排序, |
如果容器中不存在 |
如果容器中不存在 |
|
|
迭代器、指標和對容器元素的參考永遠不會失效。 |
迭代器可能會因呼叫插入或重新雜湊而失效。. |
迭代器按照比較物件定義的順序遍歷容器。 |
迭代器以任意順序遍歷容器,該順序可能會隨著元素的插入而變更,儘管相等的元素總是相鄰。 |
沒有等效的成員函數 |
閉合定址容器:可以使用本機迭代器遍歷個別儲存桶。(本機迭代器和迭代器的順序不要求具有任何對應關係。) |
可以使用 |
可以使用 |
當插入帶有提示的元素時,實作可以忽略提示。 |
操作 | 關聯容器 | 無序關聯容器 |
---|---|---|
建構空容器 |
常數時間 |
O(n),其中 n 是最小儲存桶數量。 |
從 N 個元素的範圍建構容器 |
O(N log N),如果範圍以 |
平均情況 O(N),最差情況 O(N2) |
插入單個元素 |
對數時間 |
平均情況常數時間,最差情況線性時間 |
插入帶有提示的單個元素 |
如果 |
平均情況常數時間,最差情況線性時間(即與一般插入相同)。 |
插入 N 個元素的範圍 |
N log( |
平均情況 O(N),最差情況 O(N * |
依鍵 |
O(log( |
平均情況:O( |
透過迭代器刪除單一元素 |
均攤常數時間 |
平均情況:O(1),最差情況:O( |
刪除 N 個元素的範圍 |
O(log( |
平均情況:O(N),最差情況:O( |
清除容器 |
O( |
O( |
尋找 |
對數時間 |
平均情況:O(1),最差情況:O( |
計數 |
O(log( |
平均情況:O(1),最差情況:O( |
|
對數時間 |
平均情況:O( |
|
對數時間 |
不適用 |
並行容器
Boost.Unordered 提供了 boost::concurrent_node_set
、boost::concurrent_node_map
、boost::concurrent_flat_set
和 boost::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_set
、boost::concurrent_node_map
、boost::concurrent_flat_set
和 boost::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_while
和 erase_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()
時在插入期間發生。與非並行容器一樣,在批量插入之前預留空間通常會加快處理速度。
與非並行容器的互通性
由於開放尋址和並行容器基於相同的內部資料結構,它們可以從非並行對應物有效地移動建構,反之亦然。
|
|
|
|
|
|
|
|
此互操作性在多階段情境中很方便,其中部分資料處理並行發生,而其他步驟是非並行(或非修改)的。在以下範例中,我們想要從大量的輸入字詞向量中建構直方圖:填充階段可以使用 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::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]set
和 boost::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_construct
和 std::tuple
。
交換
當進行交換時,Pred
和 Hash
目前並非透過呼叫 swap
來交換,而是使用其複製建構函式。因此,當進行交換時,可能會從其複製建構函式中擲出例外。
開放定址容器
C++ 標準目前未提供任何開放定址容器的規範可供遵循,因此 boost::unordered_flat_set
/unordered_node_set
和 boost::unordered_flat_map
/unordered_node_map
分別從 std::unordered_set
和 std::unordered_map
中汲取靈感,並在方便或受到其內部資料結構指示時,會偏離它們的介面,因為它們的內部資料結構與標準(封閉定址)所規定的截然不同。
Boost.Unordered 提供的開放定址容器僅適用於相當符合 C++11(或更新版本)的編譯器。移動語意和可變參數範本參數等語言層級的功能則不進行模擬。這些容器完全 AllocatorAware,並支援花式指標。
與 C++ 無序關聯式容器的主要差異在於
-
一般而言
-
begin()
不是常數時間。 -
erase(iterator)
不會傳回指向下一個元素的迭代器,而是傳回一個代理物件,該物件在被要求時會轉換為該迭代器;這可以避免在不需要時進行潛在的高成本迭代器遞增操作。 -
沒有用於儲存桶處理的 API(除了
bucket_count
)。 -
容器的最大載入因子由內部管理,使用者無法設定。透過公開函式
max_load
公開的最大載入量,可能會在高載入條件下因刪除而減少。
-
-
平面容器 (
boost::unordered_flat_set
和boost::unordered_flat_map
)-
value_type
必須是可移動建構的。 -
指標穩定性在重新雜湊時不會保持。
-
沒有用於節點擷取/插入的 API。
-
並行容器
C++ 標準目前沒有針對此或任何其他類型的並行資料結構的規範。boost::concurrent_flat_set
/boost::concurrent_node_set
和 boost::concurrent_flat_map
/boost::concurrent_node_map
的 API 分別模仿 std::unordered_flat_set
和 std::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 編譯器中具有並行版本。一般而言,並行容器的介面是從其非並行對應項目的介面衍生而來,方法是將迭代器替換為適用時的訪問。如果對於常規映射,iterator
和 const_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 擁有最快的封閉定址實作之一,也稱為分離鏈接。以下是表示資料結構的範例圖

分配一個「儲存桶」陣列,每個儲存桶又指向其各自的連結串列。這使得滿足儲存桶迭代的標準要求變得簡單。不幸的是,使用此佈局時,整個容器的迭代通常很慢,因為必須檢查每個儲存桶的佔用情況,當標準要求複雜度為 O(size())
時,會產生 O(bucket_count() + size())
的時間複雜度。
標準實現的規範會如下圖所示
值得注意的是,此方法僅由 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
// ...
}
實際上,額外的間接可能會對 insert
、find
和 erase
等常見操作產生顯著的效能影響。但是為了使容器的迭代快速,Boost.Unordered 引入了一個新的資料結構,「儲存桶群組」。儲存桶群組是儲存桶陣列子區段的固定寬度檢視。它包含一個位元遮罩 (std::size_t
),用於追蹤儲存桶的佔用情況,並包含兩個指標,以便它可以與非空群組形成雙向連結串列。以下是一個範例圖

因此,全容器迭代被轉換為遍歷非空儲存桶群組(常數時間複雜度的操作),從而將時間複雜度降回 O(size())
。總而言之,儲存桶群組的大小僅為 4 個字,並且它可以檢視 sizeof(std::size_t) * CHAR_BIT
個儲存桶,這表示對於所有常見的實作,每個儲存桶僅引入 4 位元的空間額外負荷。
開放定址容器
該圖顯示了 boost::unordered_flat_set
/unordered_node_set
和 boost:unordered_flat_map
/unordered_node_map
的基本內部佈局。

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

元資料字組分為 15 個 hi 位元組(每個關聯的儲存桶一個),以及一個溢位位元組(圖中的 ofw)。hi 的值為
-
如果對應的儲存桶為空,則為 0。
-
1 用於編碼稱為哨兵的特殊空儲存桶,該儲存桶在內部使用,以便在容器完全遍歷時停止迭代。
-
如果儲存桶已被佔用,則為從元素的雜湊值取得的簡化雜湊值。
當尋找雜湊值為 h 的元素時,諸如 SSE2 和 Neon 之類的 SIMD 技術可讓我們非常快速地檢查完整的元資料字組,並僅使用少數幾個 CPU 指令在所有 15 個儲存桶中尋找 h 的簡化值:可以輕易地捨棄不匹配的儲存桶,並且需要透過與對應元素進行完整比較來檢查簡化雜湊值匹配的儲存桶。如果尋找的元素不存在,則檢查溢位位元組
-
如果位置 h mod 8 中的位元為零,則查詢終止(且該元素不存在)。
-
如果該位元設定為 1(群組已溢位),則使用二次探測檢查其他群組,然後重複該過程。
插入在演算法上類似:使用 SIMD 定位空的儲存桶,當經過完整的群組時,其對應的溢位位元會設定為 1。
在沒有 SIMD 支援的架構中,邏輯佈局保持不變,但元資料字組使用我們稱之為位元交錯的技術進行編碼:此佈局允許我們僅使用標準算術和邏輯運算來模擬 SIMD,並具有相當良好的效能。

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

使用兩個層級的同步機制
-
容器層級:使用讀寫互斥鎖來控制任何操作對容器的存取。通常,即使是修改操作,此存取也是以讀取模式(即並行)進行,因此在大多數實際應用中,此層級沒有執行緒爭用。只有在重新雜湊或執行容器範圍的操作(例如交換或賦值)時,存取才會以寫入模式(阻塞)進行。
-
群組層級:每個 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
刪除
非重複元素 |
重複元素 |
重複元素, |
---|---|---|
按鍵,重複元素 |
按鍵,重複元素, |
成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
不成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
Clang 15 + libc++, x64
刪除
非重複元素 |
重複元素 |
重複元素, |
---|---|---|
按鍵,重複元素 |
按鍵,重複元素, |
成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
不成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
Visual Studio 2022 + Dinkumware, x64
刪除
非重複元素 |
重複元素 |
重複元素, |
---|---|---|
按鍵,重複元素 |
按鍵,重複元素, |
成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
不成功查詢
非重複元素 |
重複元素 |
重複元素, |
---|
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
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
Clang 15, x64
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
Visual Studio 2022, x64
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
Clang 12, ARM64
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
GCC 12, x86
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
Clang 15, x86
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
Visual Studio 2022, x86
執行插入 |
執行刪除 |
成功查詢 |
不成功查詢 |
---|
boost::concurrent_(flat|node)_map
所有基準測試都是使用以下項目建立的:
-
oneapi::tbb::concurrent_hash_map<int, int>
-
gtl::parallel_flat_hash_map<int, int>
,具有 64 個子映射 -
boost::concurrent_flat_map<int, int>
-
boost::concurrent_node_map<int, int>
原始碼可以在這裡找到。
基準測試會練習許多執行緒 T(介於 1 到 16 之間),同時執行隨機選擇的操作,這些操作包括更新、成功查詢和不成功查詢。操作中使用的鍵遵循具有不同偏斜參數的齊夫分佈:偏斜度越高,鍵在涵蓋範圍的較低值中越集中。
boost::concurrent_flat_map
和 boost::concurrent_node_map
會同時使用常規和批量訪問進行練習:在後一種情況下,查詢鍵會緩衝到本機陣列中,然後每次緩衝區達到 bulk_visit_size
時一併處理。
GCC 12, x64
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
Clang 15, x64
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
Visual Studio 2022, x64
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
Clang 12, ARM64
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
GCC 12, x86
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
Clang 15, x86
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
Visual Studio 2022, x86
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
50 萬次更新,450 萬次查詢 |
---|
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
500 萬次更新,4500 萬次查詢 |
---|
實作原理
封閉定址容器
boost::unordered_[multi]set
和 boost::unordered_[multi]map
遵循無序關聯容器的標準要求,因此介面已固定。但是,仍然有一些實作決策要做。優先事項是符合標準和可移植性。
關於雜湊表的 Wikipedia 文章對雜湊表的實作問題進行了很好的總結。
資料結構
透過指定用於存取容器儲存桶的介面,該標準幾乎要求雜湊表使用封閉定址。
可以想像編寫使用另一種方法的雜湊表。例如,它可以使用開放定址,並使用查詢鏈來充當儲存桶,但這會有一些嚴重的問題
-
標準要求指向元素的指標不能失效,因此元素不能儲存在單一陣列中,而是需要額外一層間接層——這會損失效率和大部分的記憶體優勢,而這些正是開放定址法的主要優點。
-
本機迭代器效率會非常低,並且可能無法滿足複雜度要求。
-
對於迭代器何時失效也有一些限制。由於開放定址法在高碰撞次數時效能會嚴重下降,這些限制可能會阻止在真正需要時進行重新雜湊。最大負載因子可以設定為相當低的值來解決這個問題——但標準要求它最初設定為 1.0。
-
而且由於標準是以封閉定址法為考量所撰寫的,如果效能沒有反映出這一點,使用者會感到驚訝。
因此,使用封閉定址法。
桶子數量
在雜湊表中,有兩種常見的方法來選擇儲存桶的數量。一種是使用質數數量的儲存桶,另一種是使用 2 的冪次方。
使用質數數量的儲存桶,並使用雜湊函數結果的模數來選擇儲存桶,通常會得到不錯的結果。缺點是所需的模數運算相當耗費資源。這在大多數情況下是容器過去的做法。
使用 2 的冪次方可以更快地選擇要使用的儲存桶,但代價是會損失雜湊值的較高位元。對於某些特殊設計的雜湊函數,可以這樣做並仍然獲得良好的結果,但由於容器可以接受任意雜湊函數,因此不能依賴這一點。
為了避免這種情況,可以對雜湊函數應用轉換,例如,請參閱 Thomas Wang 關於整數雜湊函數的文章。不幸的是,像 Wang 這樣的轉換需要知道雜湊值中的位元數,因此僅在 size_t
為 64 位時才使用。
自 1.79.0 版本以來,改用費氏雜湊。在此實作中,儲存桶編號是透過使用 (h * m) >> (w - k)
來決定的,其中 h
是雜湊值,m
是 2^w
除以黃金比例,w
是字組大小(32 或 64),而 2^k
是儲存桶的數量。這在速度和分配之間提供了良好的折衷。
自 1.80.0 版本以來,選擇質數作為儲存桶的數量,並搭配複雜的模數運算。這消除了像 1.79.0 版本那樣「混合」使用者雜湊函數結果的需求。
開放定址容器
C++ 無序關聯容器的標準規範對允許的實作施加了嚴格的限制,最重要的是隱含地假設了封閉定址法。稍微放寬此規範,便開啟了提供充分利用開放定址技術的容器變體的可能性。
boost::unordered_flat_set
/unordered_node_set
和 boost::unordered_flat_map
/unordered_node_map
的設計遵循了 Peter Dimov 的 Boost.Unordered 的開發計畫。我們在此討論最相關的原則。
雜湊函數
鑑於其豐富的功能和跨平台互通性,boost::hash
仍然是開放定址容器的預設雜湊函數。碰巧的是,boost::hash
對於整數和其他基本類型不具備開放定址所需的統計屬性;為了處理這個問題,我們實作了後混合階段
a ← h mulx C,
h ← high(a) xor low(a),
其中 mulx 是擴展乘法(在 64 位元架構中為 128 位元,在 32 位元環境中為 64 位元),而 high 和 low 分別是擴展字的較高和較低一半。在 64 位元架構中,C 是 264∕φ 的整數部分,而在 32 位元中,C = 0xE817FB2Du 是從 Steele 和 Vigna (2021) 獲得的。
當直接使用適合開放定址的雜湊函數時,可以透過專用的 hash_is_avalanching
特性選擇退出後混合。字串類型的 boost::hash
特化被標記為雪崩。
平台互通性
只要它們的 std::size_t
大小相同,且使用者提供的雜湊函數和相等述詞也是可互通的,boost::unordered_flat_set
/unordered_node_set
和 boost::unordered_flat_map
/unordered_node_map
的可觀察行為在不同的編譯器之間是決定性相同的 — 這包括對於相同操作序列,元素以完全相同的方式排序。
並行容器
Boost.Unordered 開放定址容器使用的相同資料結構也被選為 boost::concurrent_flat_set
/boost::concurrent_node_set
和 boost::concurrent_flat_map
/boost::concurrent_node_map
的基礎。
-
在非並行和並行場景中,開放定址比封閉定址替代方案更快。
-
開放定址佈局非常適合使用最少的鎖定進行並行存取和修改。特別是,中繼資料陣列可用於實作查找,直到實際元素比較的最後一步都是無鎖定的。
-
與 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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。
可以透過呼叫 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
= iterator
且 NodeType
= node_type
。
建構子
預設建構函式
unordered_map();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞、allocator_type()
作為分配器,以及最大負載因子為 1.0
,建構一個空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
儲存桶計數建構函式
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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_map(unordered_map const& other);
複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
具有分配器的迭代器範圍建構函式
template<class InputIterator>
unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0
建構一個空容器,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
unordered_map(unordered_map const& other, Allocator const& a);
建構一個容器,複製 other
容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a
。
具備配置器的移動建構子
unordered_map(unordered_map&& other, Allocator const& a);
建構一個容器,移動 other
容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a
。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_map(size_type n, allocator_type const& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設雜湊函數和鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_map(size_type n, hasher const& hf, allocator_type const& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0
,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, const allocator_type& a);
建構一個空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_map& operator=(unordered_map const& other);
賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。
如果 Alloc::propagate_on_container_copy_assignment
存在且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。
需求 |
|
移動賦值
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::value
為 true
,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。
需求 |
|
初始化列表賦值
unordered_map& operator=(std::initializer_list<value_type> il);
從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。
需求 |
|
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 如果 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
position
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 如果 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
原地插入
template<class P> std::pair<iterator, bool> insert(P&& obj);
透過執行 emplace(std::forward<P>(value))
將元素插入到容器中。
只有在 std::is_constructible<value_type, P&&>::value
為 true
時,才會參與多載解析。
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 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&&>::value
為 true
時,才會參與多載解析。
hint
是一個關於元素應該插入位置的建議。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type>);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
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。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函數與 emplace 類似,差別在於
而不是 emplace,後者只是將所有引數轉發到 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 只有在 |
具備提示的 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
是一個關於元素應該插入位置的建議。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函數與 emplace_hint 類似,差別在於
而不是 emplace_hint,後者只是將所有引數轉發到 關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 只有在 |
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。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 只有在 |
具備提示的 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
是一個關於元素應該插入位置的建議。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 只有在 |
透過迭代器提取
node_type extract(const_iterator position);
移除 position
指向的元素。
傳回 |
擁有元素的 |
注意 |
使用此方法提取的節點可以插入到相容的 |
透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
移除具有相當於 k
的鍵值的元素。
傳回 |
如果找到則傳回擁有元素的 |
拋出 |
僅在 |
注意 |
使用此方法提取的節點可以插入到相容的 只有在 |
使用 node_handle
插入
insert_return_type insert(node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh
所擁有的元素。
需求 |
|
傳回 |
如果 否則,如果已經存在一個具有等價鍵的元素,則回傳一個 否則,如果插入成功,則回傳一個 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用於插入從相容的 |
使用提示和 node_handle
插入
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh
所擁有的元素。
如果容器中已存在具有等價鍵的元素,則對 nh
沒有影響(即 nh
仍然包含該節點)。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果 如果容器中已存在具有等價鍵的元素,則回傳一個指向該元素的迭代器。 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用於插入從相容的 |
依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
刪除前, |
拋出 |
僅在 |
注意 |
在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
快速刪除 (quick_erase)
void quick_erase(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
erase_return_void
void erase_return_void(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
注意 |
例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。 |
合併 (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
中。
注意 |
|
查找
尋找 (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;
傳回 |
指向具有與 |
注意 |
包含 只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用 |
如果容器尚未包含具有與 |
傳回 |
|
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 只有當 |
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;
傳回 |
|
拋出 |
如果不存在此類元素,則擲出類型為 |
注意 |
只有當 |
桶子介面
儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回 |
將包含鍵為 |
後置條件 |
回傳值小於 |
注意 |
只有當 |
begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cbegin
const_local_iterator cbegin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cend
const_local_iterator cend(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
雜湊策略
重新雜湊 (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 > 0
且 a.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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
注意 |
例外規格與 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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
可以使用此程式庫提供的 API,透過 Boost.Serialization 封存/擷取 unordered_map
。支援規則和 XML 封存。
將 unordered_map 儲存到封存檔
將 unordered_map
x
的所有元素儲存到封存檔 (XML 封存) ar
。
需求 |
|
從封存檔載入 unordered_map
刪除 unordered_map
x
的所有現有元素,並從封存檔 (XML 封存) ar
插入儲存在 ar
讀取之儲存區的原始 unordered_map
other
元素的還原副本。
需求 |
|
注意 |
如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 |
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。
可以透過呼叫 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
,建構一個空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
儲存桶計數建構函式
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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_multimap(const unordered_multimap& other);
複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
移動建構函式
unordered_multimap(unordered_multimap&& other);
移動建構函式。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
具有分配器的迭代器範圍建構函式
template<class InputIterator>
unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0
建構一個空容器,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
unordered_multimap(const unordered_multimap& other, const Allocator& a);
建構一個容器,複製 other
容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a
。
具備配置器的移動建構子
unordered_multimap(unordered_multimap&& other, const Allocator& a);
建構一個容器,移動 other
容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a
。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_multimap(size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設雜湊函數和鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_multimap(size_type n, const hasher& hf, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0
,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, const allocator_type& a);
建構一個空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_multimap(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_multimap& operator=(const unordered_multimap& other);
賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。
如果 Alloc::propagate_on_container_copy_assignment
存在且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。
需求 |
|
移動賦值
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::value
為 true
,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。
需求 |
|
初始化列表賦值
unordered_multimap& operator=(std::initializer_list<value_type> il);
從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。
需求 |
|
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
修改器
emplace
template<class... Args> iterator emplace(Args&&... args);
在容器中插入一個使用引數 args
建構的物件。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
在容器中插入一個使用引數 args 建構的物件。
position
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
複製插入
iterator insert(const value_type& obj);
在容器中插入 obj
。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
移動插入
iterator insert(value_type&& obj);
在容器中插入 obj
。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
原地插入
template<class P> iterator insert(P&& obj);
透過執行 emplace(std::forward<P>(value))
將元素插入到容器中。
只有在 std::is_constructible<value_type, P&&>::value
為 true
時,才會參與多載解析。
傳回 |
指向插入元素的迭代器。 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
在容器中插入 obj
。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
在容器中插入 obj
。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 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&&>::value
為 true
時,才會參與多載解析。
hint
是一個關於元素應該插入位置的建議。
傳回 |
指向插入元素的迭代器。 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入容器中。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type> il);
將一系列元素插入容器中。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
透過迭代器提取
node_type extract(const_iterator position);
移除 position
指向的元素。
傳回 |
擁有元素的 |
注意 |
使用此方法提取的節點可以插入到相容的 |
透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
移除具有相當於 k
的鍵值的元素。
傳回 |
如果找到則傳回擁有元素的 |
拋出 |
僅在 |
注意 |
使用此方法提取的節點可以插入到相容的 只有在 |
使用 node_handle
插入
iterator insert(node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則插入 nh
所擁有的元素。
需求 |
|
傳回 |
如果 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用來插入從相容的 |
使用提示和 node_handle
插入
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則插入 nh
所擁有的元素。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用來插入從相容的 |
依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
刪除前, |
拋出 |
僅在 |
注意 |
在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
快速刪除 (quick_erase)
void quick_erase(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
erase_return_void
void erase_return_void(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
注意 |
例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。 |
合併 (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
中。
注意 |
|
查找
尋找 (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;
傳回 |
指向具有與 |
注意 |
包含 只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
桶子介面
儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回 |
將包含鍵為 |
後置條件 |
回傳值小於 |
注意 |
只有當 |
begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cbegin
const_local_iterator cbegin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cend
const_local_iterator cend(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
雜湊策略
重新雜湊 (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 > 0
且 a.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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
注意 |
例外規格與 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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
unordered_multimap
可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。
將 unordered_multimap 儲存到封存檔
將 unordered_multimap
x
的所有元素儲存到封存檔 (XML 封存檔) ar
。
需求 |
|
從封存檔載入 unordered_multimap
刪除 unordered_multimap
x
的所有先前存在的元素,並從封存檔 (XML 封存檔) ar
插入還原的原始 unordered_multimap
other
的元素副本,這些副本儲存在 ar
讀取的儲存空間中。
需求 |
|
注意 |
如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 |
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
元素被組織成儲存桶。具有相同雜湊碼的鍵儲存在同一個儲存桶中。
可以透過呼叫 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
= iterator
且 NodeType
= node_type
。
建構子
預設建構函式
unordered_set();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞、allocator_type()
作為分配器,以及最大負載因子為 1.0
,建構一個空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
儲存桶計數建構函式
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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_set(const unordered_set& other);
複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
具有分配器的迭代器範圍建構函式
template<class InputIterator>
unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0
建構一個空容器,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
unordered_set(const unordered_set& other, const Allocator& a);
建構一個容器,複製 other
容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a
。
具備配置器的移動建構子
unordered_set(unordered_set&& other, const Allocator& a);
建構一個容器,移動 other
容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a
。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_set(size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設雜湊函數和鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_set(size_type n, const hasher& hf, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0
,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, const allocator_type& a);
建構一個空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_set& operator=(const unordered_set& other);
賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。
如果 Alloc::propagate_on_container_copy_assignment
存在且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。
需求 |
|
移動賦值
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::value
為 true
,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。
需求 |
|
初始化列表賦值
unordered_set& operator=(std::initializer_list<value_type> il);
從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。
需求 |
|
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有等效值的元素,則在容器中插入一個使用引數 args
建構的物件。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果執行了插入操作,則迭代器指向新插入的元素。否則,它指向具有等效值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有等效值的元素,則在容器中插入一個使用引數 args
建構的物件。
position
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 僅當 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具有提示的透明插入
template<class K> iterator insert(const_iterator hint, K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 僅當 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type>);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
透過迭代器提取
node_type extract(const_iterator position);
移除 position
指向的元素。
傳回 |
擁有元素的 |
注意 |
在 C++17 中,使用此方法提取的節點可以插入到相容的 |
按值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
移除具有相當於 k
的鍵值的元素。
傳回 |
如果找到則傳回擁有元素的 |
拋出 |
僅在 |
注意 |
在 C++17 中,使用此方法提取的節點可以插入到相容的 只有在 |
使用 node_handle
插入
insert_return_type insert(node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh
所擁有的元素。
需求 |
|
傳回 |
如果 否則,如果已經存在一個具有等價鍵的元素,則回傳一個 否則,如果插入成功,則回傳一個 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 在 C++17 中,這可以用來插入從相容的 |
使用提示和 node_handle
插入
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則,只有在容器中沒有具有相等鍵值的元素時,才會插入 nh
所擁有的元素。
如果容器中已存在具有等價鍵的元素,則對 nh
沒有影響(即 nh
仍然包含該節點)。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果 如果容器中已存在具有等價鍵的元素,則回傳一個指向該元素的迭代器。 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用來插入從相容的 |
依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
刪除前, |
拋出 |
僅在 |
注意 |
在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。 |
按值刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
快速刪除 (quick_erase)
void quick_erase(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
erase_return_void
void erase_return_void(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
注意 |
例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。 |
合併 (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
中。
注意 |
|
查找
尋找 (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;
傳回 |
指向具有與 |
注意 |
包含 只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
桶子介面
儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回 |
將包含鍵為 |
後置條件 |
回傳值小於 |
注意 |
只有當 |
begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cbegin
const_local_iterator cbegin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cend
const_local_iterator cend(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
雜湊策略
重新雜湊 (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 > 0
且 a.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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
注意 |
例外規格與 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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
unordered_set
可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。
將 unordered_set 儲存到封存檔
將 unordered_set
x
的所有元素儲存到封存檔 (XML 封存檔) ar
。
需求 |
|
從封存檔載入 unordered_set
刪除 unordered_set
x
的所有先前存在的元素,並從封存檔 (XML 封存檔) ar
插入還原的原始 unordered_set
other
的元素副本,這些副本儲存在 ar
讀取的儲存空間中。
需求 |
|
注意 |
如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 |
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
這些元素會組織到儲存桶中。具有相同雜湊碼的鍵會儲存在同一個儲存桶中,而具有等效鍵的元素會彼此相鄰儲存。
可以透過呼叫 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
,建構一個空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
儲存桶計數建構函式
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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_multiset(const unordered_multiset& other);
複製建構函式。複製包含的元素、雜湊函數、述詞、最大負載因子和分配器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
移動建構函式
unordered_multiset(unordered_multiset&& other);
移動建構函式。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
具有分配器的迭代器範圍建構函式
template<class InputIterator>
unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器、預設雜湊函數和鍵相等述詞以及最大負載因子 1.0
建構一個空容器,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
unordered_multiset(const unordered_multiset& other, const Allocator& a);
建構一個容器,複製 other
容器內的元素、雜湊函數、述詞、最大載入因子,但使用配置器 a
。
具備配置器的移動建構子
unordered_multiset(unordered_multiset&& other, const Allocator& a);
建構一個容器,移動 other
容器內的元素,並具有雜湊函數、述詞和最大載入因子,但使用配置器 a
。
注意 |
這是使用 Boost.Move 實作的。 |
需求 |
|
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_multiset(size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設雜湊函數和鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_multiset(size_type n, const hasher& hf, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,預設鍵值相等述詞,a
作為配置器,最大載入因子為 1.0
。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,預設雜湊函數和鍵值相等述詞,最大載入因子為 1.0
,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il, const allocator_type& a);
建構一個空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il, size_type n, const allocator_type& a)
建構一個至少有 n
個儲存桶的空容器,使用 a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_multiset(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空容器,使用 hf
作為雜湊函數,a
作為配置器,最大載入因子為 1.0,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_multiset& operator=(const unordered_multiset& other);
賦值運算子。複製包含的元素、雜湊函數、述詞和最大載入因子,但不複製配置器。
如果 Alloc::propagate_on_container_copy_assignment
存在且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則配置器會被覆寫,如果不是,則複製的元素會使用現有的配置器建立。
需求 |
|
移動賦值
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::value
為 true
,則配置器會被覆寫,如果不是,則移動的元素會使用現有的配置器建立。
需求 |
|
初始化列表賦值
unordered_multiset& operator=(std::initializer_list<value_type> il);
從初始化列表中的值賦值。所有現有的元素都會被新的元素覆寫或銷毀。
需求 |
|
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
修改器
emplace
template<class... Args> iterator emplace(Args&&... args);
在容器中插入一個使用引數 args 建構的物件。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
在容器中插入一個使用引數 args 建構的物件。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
複製插入
iterator insert(const value_type& obj);
在容器中插入 obj
。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
移動插入
iterator insert(value_type&& obj);
在容器中插入 obj
。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
在容器中插入 obj
。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
在容器中插入 obj
。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
指向插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入容器中。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type> il);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 |
透過迭代器提取
node_type extract(const_iterator position);
移除 position
指向的元素。
傳回 |
擁有元素的 |
注意 |
使用此方法提取的節點可以插入到相容的 |
按值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
移除具有相當於 k
的鍵值的元素。
傳回 |
如果找到則傳回擁有元素的 |
拋出 |
僅在 |
注意 |
使用此方法提取的節點可以插入到相容的 只有在 |
使用 node_handle
插入
iterator insert(node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則插入 nh
所擁有的元素。
需求 |
|
傳回 |
如果 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用來插入從相容的 |
使用提示和 node_handle
插入
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
為空,則不會產生任何作用。
否則插入 nh
所擁有的元素。
hint
是一個關於元素應該插入位置的建議。
需求 |
|
傳回 |
如果 否則,回傳一個指向新插入元素的迭代器。 |
拋出 |
如果除了呼叫雜湊函數之外的操作擲出例外,則該函數沒有任何作用。 |
注意 |
關於提示的含義,標準相當模糊。但唯一可行的方法,也是 Boost.Unordered 支援的唯一方法,是指向具有相同鍵值的現有元素。 可能會使迭代器失效,但只有在插入導致載入因子大於或等於最大載入因子的情況下才會失效。 指向元素的指標和參考永遠不會失效。 這可以用來插入從相容的 |
依位置刪除
iterator erase(iterator position);
iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
刪除前, |
拋出 |
僅在 |
注意 |
在較舊的版本中,這可能效率低下,因為它必須搜尋多個儲存桶才能找到回傳的迭代器的位置。資料結構已變更,因此不再是這種情況,且已棄用替代的刪除方法。 |
按值刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& x);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
快速刪除 (quick_erase)
void quick_erase(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
erase_return_void
void erase_return_void(const_iterator position);
刪除 position
所指向的元素。
拋出 |
僅在 在此實作中,此多載不會呼叫任何函數物件的方法,因此不會擲出例外,但在其他實作中可能不是這樣。 |
注意 |
實作此方法的原因是從刪除回傳下一個元素的迭代器很耗費資源,但容器已重新設計,因此不再是這種情況。因此,現在已棄用此方法。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
注意 |
例外規格與 C++11 標準不太相同,因為相等述詞和雜湊函數是使用其複製建構函式交換的。 |
合併 (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
中。
注意 |
|
查找
尋找 (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;
傳回 |
指向具有與 |
注意 |
包含 只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
桶子介面
儲存桶 (bucket)
size_type bucket(const key_type& k) const;
template<class K> size_type bucket(const K& k) const;
傳回 |
將包含鍵為 |
後置條件 |
回傳值小於 |
注意 |
只有當 |
begin
local_iterator begin(size_type n);
const_local_iterator begin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
end
local_iterator end(size_type n);
const_local_iterator end(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cbegin
const_local_iterator cbegin(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
cend
const_local_iterator cend(size_type n) const;
需求 |
|
傳回 |
指向索引為 |
雜湊策略
重新雜湊 (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 > 0
且 a.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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
注意 |
例外規格與 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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
unordered_multiset
可以使用此程式庫提供的 API,透過 Boost.Serialization 進行封存/擷取。支援一般封存檔和 XML 封存檔。
將 unordered_multiset 儲存到封存檔
將 unordered_multiset
x
的所有元素儲存到封存檔 (XML 封存檔) ar
。
需求 |
|
從封存檔載入 unordered_multiset
刪除 unordered_multiset
x
的所有先前存在的元素,並從封存檔 (XML 封存檔) ar
插入還原的原始 unordered_multiset
other
的元素副本,這些副本儲存在 ar
讀取的儲存空間中。
需求 |
|
注意 |
如果封存檔是使用 Boost 1.84 之前的版本儲存的,則必須全域定義組態巨集 |
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
雜湊特性
概要
// #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_avalanching
為void
(不建議使用此用法),則為true
, -
否則格式不正確。
然後,使用者可以透過在 Hash
的定義中嵌入適當的 is_avalanching
typedef,或者直接將 hash_is_avalanching<Hash>
特製化為具有嵌入的編譯時期常數 value
並設定為 true
的類別,來宣告雜湊函數 Hash
為雪崩式。
如果 hash_is_avalanching<Hash>::value
為 true
,則開放定址和並行容器會按原樣使用提供的雜湊函數 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; };
統計資料摘要類型
提供數值序列的平均值、變異數和標準差。
類別模板 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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
容器的元素保存在內部儲存桶陣列中。一個元素會插入到由其雜湊碼確定的儲存桶中,但如果該儲存桶已被佔用(發生碰撞),則會使用原始位置附近可用的儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或者透過呼叫 rehash
/reserve
增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor()
,除非在實作決定允許更高負載的小尺寸情況下。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
型別定義
typedef implementation-defined iterator;
值類型為 value_type
的迭代器。
迭代器類別至少是前向迭代器。
可轉換為 const_iterator
。
typedef implementation-defined const_iterator;
值類型為 value_type
的常數迭代器。
迭代器類別至少是前向迭代器。
建構子
預設建構函式
unordered_flat_map();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞和 allocator_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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
中的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_flat_map(unordered_flat_map const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
移動建構函式
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)
中的元素插入其中。
需求 |
|
具有分配器的複製建構函式
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()
。
複雜度 |
常數時間。 |
並行性 |
在 |
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_flat_map(size_type n, allocator_type const& a);
使用 hf
作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_flat_map(size_type n, hasher const& hf, allocator_type const& a);
使用 hf
作為雜湊函數、預設的鍵相等述詞和 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
使用 a
作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
使用 hf
作為雜湊函數、a
作為配置器,以及預設的鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_flat_map& operator=(unordered_flat_map const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動賦值運算子。銷毀先前存在的元素,交換 other
的雜湊函數和述詞,如果存在 Alloc::propagate_on_container_move_assignment
且 Alloc::propagate_on_container_move_assignment::value
為 true
,則從 other
移動賦值配置器。如果此時配置器等於 other.get_allocator()
,則 other
的內部儲存桶陣列會直接轉移到新的容器;否則,會插入 other
元素的移動建構副本。如果 啟用 統計資料,則僅在最終配置器等於 other.get_allocator()
時,才會從 other
轉移內部統計資訊,並始終呼叫 other.reset_stats()
。
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
複雜度 |
O( |
cbegin
const_iterator cbegin() const noexcept;
傳回 |
一個 |
複雜度 |
O( |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 如果 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
position
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 如果 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
std::pair<iterator, bool> insert(const init_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 形式為 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
std::pair<iterator, bool> insert(init_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 形式為 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, const init_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 形式為 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
iterator insert(const_iterator hint, init_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 形式為 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
插入初始化列表
void insert(std::initializer_list<value_type>);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
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
的現有元素,則此函數不會執行任何動作。
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函式類似於 emplace,不同之處在於,如果存在具有等效鍵的元素,則不會建構
與 emplace 不同,後者只是將所有引數轉發到 可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 只有在 |
具備提示的 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
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函式類似於 emplace_hint,不同之處在於,如果存在具有等效鍵的元素,則不會建構
與 emplace_hint 不同,後者只是將所有引數轉發到 可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 只有在 |
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)))
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 只有在 |
具備提示的 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
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 只有在 |
依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
一個不透明物件,可以隱式轉換為刪除前緊接在 |
拋出 |
無。 |
注意 |
傳回的不透明物件只能被捨棄或立即轉換為 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
在此實作中無任何作用(不會呼叫 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
清除 (clear)
void clear() noexcept;
刪除容器中的所有元素。
後置條件 |
|
合併 (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
中刪除它們。
查找
尋找 (find)
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class K>
iterator find(const K& k);
傳回 |
指向鍵值與 |
注意 |
只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用 |
如果容器尚未包含鍵值與 |
傳回 |
|
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 只有當 |
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;
傳回 |
|
拋出 |
如果不存在此類元素,則擲出類型為 |
注意 |
只有當 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。 |
注意 |
建構、重新雜湊或清除後,容器的最大負載至少為 |
重新雜湊 (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
類似,此函數可用於增加或縮減容器中的儲存桶數量。
使迭代器、指標和參考失效,並變更元素的順序。
拋出 |
如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 unordered_flat_map
。支援一般和 XML 封存。
將 unordered_flat_map 儲存至封存
將 unordered_flat_map
x
的所有元素儲存到封存 (XML 封存) ar
。
需求 |
|
從封存載入 unordered_flat_map
刪除 unordered_flat_map
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入還原的 unordered_flat_map
other
元素的副本,這些副本已儲存至 ar
讀取的儲存空間。
需求 |
|
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
容器的元素保存在內部儲存桶陣列中。一個元素會插入到由其雜湊碼確定的儲存桶中,但如果該儲存桶已被佔用(發生碰撞),則會使用原始位置附近可用的儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或者透過呼叫 rehash
/reserve
增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor()
,除非在實作決定允許更高負載的小尺寸情況下。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
型別定義
typedef implementation-defined iterator;
值類型為 value_type
的常數迭代器。
迭代器類別至少是前向迭代器。
可轉換為 const_iterator
。
typedef implementation-defined const_iterator;
值類型為 value_type
的常數迭代器。
迭代器類別至少是前向迭代器。
建構子
預設建構函式
unordered_flat_set();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞和 allocator_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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
中的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_flat_set(unordered_flat_set const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
移動建構函式
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)
中的元素插入其中。
需求 |
|
具有分配器的複製建構函式
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()
。
複雜度 |
常數時間。 |
並行性 |
在 |
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_flat_set(size_type n, allocator_type const& a);
使用 hf
作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_flat_set(size_type n, hasher const& hf, allocator_type const& a);
使用 hf
作為雜湊函數、預設的鍵相等述詞和 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
使用 a
作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
使用 hf
作為雜湊函數、a
作為配置器,以及預設的鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_flat_set& operator=(unordered_flat_set const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動指派運算子。銷毀先前存在的元素、從 other
交換雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則從 other
移動指派配置器。如果此時配置器等於 other.get_allocator()
,則 other
的內部儲存桶陣列會直接傳輸至新的容器;否則,會插入 other
元素的移動建構副本。如果 啟用 統計資料,則僅當最終配置器等於 other.get_allocator()
時才會從 other
傳輸內部統計資訊,並且一律呼叫 other.reset_stats()
。
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
複雜度 |
O( |
cbegin
const_iterator cbegin() const noexcept;
傳回 |
一個 |
複雜度 |
O( |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
position
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 僅當 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 |
具有提示的透明插入
template<class K> std::pair<iterator, bool> insert(const_iterator hint, K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可以使迭代器、指標和參考失效,但僅當插入導致負載大於最大負載時才失效。 僅當 |
插入迭代器範圍
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);
刪除 position
所指向的元素。
傳回 |
一個不透明物件,可以隱式轉換為刪除前緊接在 |
拋出 |
無。 |
注意 |
傳回的不透明物件只能被捨棄或立即轉換為 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
在此實作中無任何作用(不會呼叫 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
清除 (clear)
void clear() noexcept;
刪除容器中的所有元素。
後置條件 |
|
合併 (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
中刪除它們。
查找
尋找 (find)
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class K>
iterator find(const K& k);
傳回 |
指向鍵值與 |
注意 |
只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。 |
注意 |
建構、重新雜湊或清除後,容器的最大負載至少為 |
重新雜湊 (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
類似,此函數可用於增加或縮減容器中的儲存桶數量。
使迭代器、指標和參考失效,並變更元素的順序。
拋出 |
如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
可以使用此程式庫提供的 API,透過 Boost.Serialization 來封存/擷取 unordered_flat_set
。支援一般和 XML 封存。
將 unordered_flat_set 儲存至封存
將 unordered_flat_set
x
的所有元素儲存到封存 (XML 封存) ar
。
需求 |
|
從封存載入 unordered_flat_set
刪除 unordered_flat_set
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入還原的 unordered_flat_set
other
元素的副本,這些副本已儲存至 ar
讀取的儲存空間。
需求 |
|
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 unordered_node_map
boost::unordered_node_map
— 一個以節點為基礎的開放定址無序關聯容器,可將唯一鍵值與另一個值建立關聯。
boost::unordered_node_map
使用與 boost::unordered_flat_map
相同的開放定址配置,但由於以節點為基礎,因此提供指標穩定性和節點處理功能。其效能介於 boost::unordered_map
和 boost::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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
容器的元素節點會保留在內部「儲存桶陣列」中。節點會插入由其元素雜湊碼決定的儲存桶中,但如果該儲存桶已被佔用 (發生「衝突」),則會使用原始位置附近的可用儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或者透過呼叫 rehash
/reserve
增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor()
,除非在實作決定允許更高負載的小尺寸情況下。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
型別定義
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
= iterator
且 NodeType
= node_type
。
建構子
預設建構函式
unordered_node_map();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞和 allocator_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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
中的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
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)
中的元素插入其中。
需求 |
|
具有分配器的複製建構函式
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()
。
複雜度 |
常數時間。 |
並行性 |
在 |
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_node_map(size_type n, allocator_type const& a);
使用 hf
作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_node_map(size_type n, hasher const& hf, allocator_type const& a);
使用 hf
作為雜湊函數、預設的鍵相等述詞和 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_node_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
使用 a
作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
使用 hf
作為雜湊函數、a
作為配置器,以及預設的鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_node_map& operator=(unordered_node_map const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動指派運算子。銷毀先前存在的元素、從 other
交換雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則從 other
移動指派配置器。如果此時配置器等於 other.get_allocator()
,則 other
的內部儲存桶陣列會直接傳輸至新的容器;否則,會插入 other
元素的移動建構副本。如果 啟用 統計資料,則僅當最終配置器等於 other.get_allocator()
時才會從 other
傳輸內部統計資訊,並且一律呼叫 other.reset_stats()
。
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
複雜度 |
O( |
cbegin
const_iterator cbegin() const noexcept;
傳回 |
一個 |
複雜度 |
O( |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 如果 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
position
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 如果 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
std::pair<iterator, bool> insert(const init_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 形式為 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
std::pair<iterator, bool> insert(init_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 形式為 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
iterator insert(const_iterator hint, const init_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 形式為 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
iterator insert(const_iterator hint, init_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 形式為 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type>);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
插入節點
insert_return_type insert(node_type&& nh);
如果 nh
不為空,則僅當容器中沒有鍵值與 nh.key()
相等的元素時,才會在容器中插入關聯元素。當函式傳回時,nh
為空。
傳回 |
一個由
|
拋出 |
如果因呼叫 |
注意 |
如果 |
使用提示插入節點
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
不為空,則當且僅當容器中沒有與 nh.key()
等效鍵的元素時,才將關聯的元素插入容器。如果插入成功,nh
會變為空,否則不會變更。
hint
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果 |
拋出 |
如果因呼叫 |
注意 |
如果 |
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
的現有元素,則此函數不會執行任何動作。
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函式類似於 emplace,不同之處在於,如果存在具有等效鍵的元素,則不會建構
與 emplace 不同,後者只是將所有引數轉發給 可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 只有在 |
具備提示的 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
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
此函式類似於 emplace_hint,不同之處在於,如果存在具有等效鍵的元素,則不會建構
與 emplace_hint 不同,後者只是將所有引數轉發給 可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 只有在 |
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)))
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 只有在 |
具備提示的 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
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 只有在 |
依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
一個不透明物件,可以隱式轉換為刪除前緊接在 |
拋出 |
無。 |
注意 |
傳回的不透明物件只能被捨棄或立即轉換為 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
在此實作中無任何作用(不會呼叫 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
依位置提取
node_type extract(const_iterator position);
提取 position
所指向的元素。
傳回 |
一個包含提取元素的 |
拋出 |
無。 |
透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
提取具有與 k
等效鍵的元素(如果存在)。
傳回 |
一個包含提取元素的 |
拋出 |
僅在 |
注意 |
只有當 |
清除 (clear)
void clear() noexcept;
刪除容器中的所有元素。
後置條件 |
|
合併 (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
中的元素節點傳輸過來。
需求 |
|
注意 |
使傳輸元素的迭代器失效。如果 |
查找
尋找 (find)
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class K>
iterator find(const K& k);
傳回 |
指向鍵值與 |
注意 |
只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
operator[]
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);
template<class K> mapped_type& operator[](K&& k);
作用 |
如果容器尚未包含鍵值與 |
傳回 |
|
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 只有當 |
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;
傳回 |
|
拋出 |
如果不存在此類元素,則擲出類型為 |
注意 |
只有當 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。 |
注意 |
建構、重新雜湊或清除後,容器的最大負載至少為 |
重新雜湊 (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
類似,此函數可用於增加或縮減容器中的儲存桶數量。
使迭代器失效並變更元素的順序。
拋出 |
如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
可以透過此程式庫提供的 API,使用 Boost.Serialization 封存/擷取 unordered_node_map
。支援常規和 XML 封存。
將 unordered_node_map 儲存到封存
將 unordered_node_map
x
的所有元素儲存到封存 (XML 封存) ar
。
需求 |
|
從封存載入 unordered_node_map
刪除 unordered_node_map
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入儲存在 ar
讀取儲存區的原始 unordered_node_map
other
元素的還原副本。
需求 |
|
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 unordered_node_set
boost::unordered_node_set
— 一個基於節點的開放定址無序關聯容器,用於儲存唯一值。
boost::unordered_node_set
使用類似於 boost::unordered_flat_set
的開放定址佈局,但由於是基於節點的,因此它提供指標穩定性和節點處理功能。其效能介於 boost::unordered_set
和 boost::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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與容器的值類型相同。支援使用花式指標的分配器。 |
容器的元素節點會保留在內部「儲存桶陣列」中。節點會插入由其元素雜湊碼決定的儲存桶中,但如果該儲存桶已被佔用 (發生「衝突」),則會使用原始位置附近的可用儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或者透過呼叫 rehash
/reserve
增加。容器的負載因子(元素數量除以儲存桶數量)永遠不會大於 max_load_factor()
,除非在實作決定允許更高負載的小尺寸情況下。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
型別定義
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
= iterator
且 NodeType
= node_type
。
建構子
預設建構函式
unordered_node_set();
使用 hasher()
作為雜湊函數、key_equal()
作為鍵相等述詞和 allocator_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
個儲存桶的空容器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
中的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
unordered_node_set(unordered_node_set const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
移動建構函式
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)
中的元素插入其中。
需求 |
|
具有分配器的複製建構函式
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()
。
複雜度 |
常數時間。 |
並行性 |
在 |
初始化列表建構子
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
中的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
unordered_node_set(size_type n, allocator_type const& a);
使用 hf
作為雜湊函數、預設的雜湊函數和鍵相等述詞,以及 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
unordered_node_set(size_type n, hasher const& hf, allocator_type const& a);
使用 hf
作為雜湊函數、預設的鍵相等述詞和 a
作為配置器,建構一個至少有 n
個儲存桶的空容器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
unordered_node_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
使用 a
作為配置器,以及預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 [f, l)
中的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
中的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個空的容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
使用 a
和預設的雜湊函數和鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
unordered_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
使用 hf
作為雜湊函數、a
作為配置器,以及預設的鍵相等述詞,建構一個至少有 n
個儲存桶的空容器,並將 il
中的元素插入其中。
需求 |
|
賦值
複製賦值
unordered_node_set& operator=(unordered_node_set const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動指派運算子。銷毀先前存在的元素,從 other
交換雜湊函式和述詞,如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則會從 other
移動指派配置器。如果此時配置器等於 other.get_allocator()
,則 other
的內部儲存桶陣列會直接轉移到新容器;否則,會插入 other
元素的移動建構副本。如果 啟用統計資料,則當且僅當最終配置器等於 other.get_allocator()
時,才會將內部統計資訊從 other
傳輸過來,並一律呼叫 other.reset_stats()
。
迭代器
begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
傳回 |
一個指向容器第一個元素的迭代器,如果容器是空的,則傳回容器的超出尾端值。 |
複雜度 |
O( |
cbegin
const_iterator cbegin() const noexcept;
傳回 |
一個 |
複雜度 |
O( |
修改器
emplace
template<class... Args> std::pair<iterator, bool> emplace(Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
emplace_hint
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
如果容器中沒有具有相等鍵值的元素,則使用引數 args
建構的物件插入到容器中。
position
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
複製插入
std::pair<iterator, bool> insert(const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
移動插入
std::pair<iterator, bool> insert(value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
透明插入
template<class K> std::pair<iterator, bool> insert(K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 僅當 |
具備提示的複製插入
iterator insert(const_iterator hint, const value_type& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
具備提示的移動插入
iterator insert(const_iterator hint, value_type&& obj);
如果容器中沒有具有相等鍵值的元素,則將 obj
插入容器中。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
具有提示的透明插入
template<class K> std::pair<iterator, bool> insert(const_iterator hint, K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
hint
是建議插入元素的位置。此實作會忽略它。
需求 |
|
傳回 |
如果發生插入,則傳回類型的布林值元件為 true。 如果發生插入,則迭代器指向新插入的元素。否則,它指向具有相等鍵值的元素。 |
拋出 |
如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 僅當 |
插入迭代器範圍
template<class InputIterator> void insert(InputIterator first, InputIterator last);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
插入初始化列表
void insert(std::initializer_list<value_type>);
將一系列元素插入到容器中。只有在容器中沒有具有相等鍵值的元素時,才會插入元素。
需求 |
|
拋出 |
當插入單一元素時,如果因呼叫 |
注意 |
可能會使迭代器失效,但僅當插入導致負載大於最大負載時才會失效。 |
插入節點
insert_return_type insert(node_type&& nh);
如果 nh
不為空,則當且僅當容器中沒有與 nh.value()
等效鍵的元素時,才將關聯的元素插入容器。當函式傳回時,nh
為空。
傳回 |
一個由
|
拋出 |
如果因呼叫 |
注意 |
如果 |
使用提示插入節點
iterator insert(const_iterator hint, node_type&& nh);
如果 nh
不為空,則當且僅當容器中沒有與 nh.value()
等效鍵的元素時,才將關聯的元素插入容器。如果插入成功,nh
會變為空,否則不會變更。
hint
是建議插入元素的位置。此實作會忽略它。
傳回 |
如果 |
拋出 |
如果因呼叫 |
注意 |
如果 |
依位置刪除
convertible-to-iterator erase(iterator position);
convertible-to-iterator erase(const_iterator position);
刪除 position
所指向的元素。
傳回 |
一個不透明物件,可以隱式轉換為刪除前緊接在 |
拋出 |
無。 |
注意 |
傳回的不透明物件只能被捨棄或立即轉換為 |
依鍵刪除
size_type erase(const key_type& k);
template<class K> size_type erase(K&& k);
刪除所有鍵與 k
等價的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
僅在 |
注意 |
只有在 |
刪除範圍
iterator erase(const_iterator first, const_iterator last);
刪除從 first
到 last
範圍內的元素。
傳回 |
刪除的元素之後的迭代器,即 |
拋出 |
在此實作中無任何作用(不會呼叫 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
拋出 |
除非 |
依位置提取
node_type extract(const_iterator position);
提取 position
所指向的元素。
傳回 |
一個包含提取元素的 |
拋出 |
無。 |
透過鍵值提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
提取具有與 k
等效鍵的元素(如果存在)。
傳回 |
一個包含提取元素的 |
拋出 |
僅在 |
注意 |
只有當 |
清除 (clear)
void clear() noexcept;
刪除容器中的所有元素。
後置條件 |
|
合併 (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
中的元素節點傳輸過來。
需求 |
|
注意 |
使傳輸元素的迭代器失效。如果 |
查找
尋找 (find)
iterator find(const key_type& k);
const_iterator find(const key_type& k) const;
template<class K>
iterator find(const K& k);
傳回 |
指向鍵值與 |
注意 |
只有當 |
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指出容器中是否存在具有與 |
注意 |
只有當 |
相等範圍 (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;
傳回 |
包含所有具有與 |
注意 |
只有當 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
容器在不重新雜湊的情況下可容納的最大元素數量,假設不再刪除任何元素。 |
注意 |
建構、重新雜湊或清除後,容器的最大負載至少為 |
重新雜湊 (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
類似,此函數可用於增加或縮減容器中的儲存桶數量。
使迭代器失效並變更元素的順序。
拋出 |
如果擲出例外,除非該例外是由容器的雜湊函數或比較函數擲出的,否則該函數不會產生任何作用。 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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)));
交換 x
和 y
的內容。
如果宣告了 Allocator::propagate_on_container_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則交換容器的配置器。否則,與不相等配置器交換會導致未定義的行為。
作用 |
|
拋出 |
除非 |
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
的所有元素。
傳回 |
已刪除的元素數量。 |
注意 |
等同於
|
序列化
可以透過此程式庫提供的 API,使用 Boost.Serialization 封存/擷取 unordered_node_set
。支援常規和 XML 封存。
將 unordered_node_set 儲存到封存
將 unordered_node_set
x
的所有元素儲存到封存 (XML 封存) ar
。
需求 |
|
從封存載入 unordered_node_set
刪除 unordered_node_set
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入儲存在 ar
讀取儲存區的原始 unordered_node_set
other
元素的還原副本。
需求 |
|
將迭代器/const_iterator 儲存到封存檔
將 iterator
(const_iterator
) it
的位置資訊儲存到封存檔 (XML 封存檔) ar
。it
可以是 end()
迭代器。
需求 |
|
從封存檔載入迭代器/const_iterator
使 iterator
(const_iterator
) it
指向從封存檔 (XML 封存檔) ar
讀取的儲存空間中所儲存的原始 iterator
(const_iterator
) 的還原位置。
需求 |
如果 |
類別模板 concurrent_flat_map
boost::concurrent_flat_map
— 一個將唯一鍵與另一個值相關聯,並允許並行元素插入、刪除、查閱和存取,而無需外部同步機制的雜湊表。
即使它充當容器,boost::concurrent_flat_map
並未對標準 C++ Container 概念建模。特別是,不提供迭代器和相關作業 (begin
、end
等)。元素存取和修改是透過使用者提供的存取函式完成的,這些函式會傳遞給 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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
配置器的值類型與資料表的值類型相同。支援使用 花俏指標的配置器。 |
資料表的元素會保留在內部儲存桶陣列中。元素會插入到由其雜湊碼決定的儲存桶中,但如果儲存桶已佔用 (衝突),則會使用原始位置附近的可用儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或透過呼叫 rehash
/reserve
來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor()
,除了實作可能會決定允許更高載入的小型大小之外。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
並行需求和保證
需要在相同的 Hash
或 Pred
常數執行個體上並行呼叫 operator()
,而不會引入資料競爭。對於 Alloc
為 Allocator
或從 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
一般而言,如果 Hash
、Pred
和 Allocator
這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。
除了銷毀操作外,在同一個 concurrent_flat_map
實例上併發呼叫任何操作都不會引入資料競爭 — 也就是說,它們是執行緒安全的。
如果某個操作 op 被明確指定為阻塞於 x
,其中 x
是 boost::concurrent_flat_map
的一個實例,則先前對 x
的阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_flat_map
的阻塞操作會依序執行。
如果某個操作僅在發出內部重新雜湊時才阻塞於 x
,則稱該操作阻塞於 x
的重新雜湊。
當由 boost::concurrent_flat_map
內部執行時,使用者提供的訪問函數對傳遞的元素執行以下操作不會引入資料競爭:
-
對元素的讀取存取。
-
對元素的不可變修改。
-
對元素的可變修改。
-
在接受兩個訪問函數的容器函數中,總是針對第一個函數。
-
在名稱不包含
cvisit
的非常數容器函數中,針對最後一個(或唯一)的訪問函數。
-
任何插入或修改元素 e
的 boost::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
發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。
建構子
預設建構函式
concurrent_flat_map();
使用 hasher()
作為雜湊函數,key_equal()
作為鍵相等謂詞,以及 allocator_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
作為分配器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
concurrent_flat_map(concurrent_flat_map const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
並行性 |
在 |
移動建構函式
concurrent_flat_map(concurrent_flat_map&& other);
移動建構函式。other
的內部儲存桶陣列直接轉移到新表格。雜湊函數、謂詞和分配器從 other
移動建構。如果 已啟用統計資訊,則從 other
轉移內部統計資訊並呼叫 other.reset_stats()
。
並行性 |
在 |
具有分配器的迭代器範圍建構函式
template<class InputIterator>
concurrent_flat_map(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
concurrent_flat_map(concurrent_flat_map const& other, Allocator const& a);
建構一個表格,複製 other
包含的元素、雜湊函數和謂詞,但使用分配器 a
。
並行性 |
在 |
具備配置器的移動建構子
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()
。
並行性 |
在 |
從 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( |
初始化列表建構子
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
的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
concurrent_flat_map(size_type n, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
concurrent_flat_map(size_type n, hasher const& hf, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l)
的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
以及預設雜湊函數和鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_flat_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,a
作為分配器,以及預設鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
賦值
複製賦值
concurrent_flat_map& operator=(concurrent_flat_map const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動賦值運算子。銷毀先前存在的元素,交換來自 other
的雜湊函數和謂詞,如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則從 other
移動賦值分配器。如果此時分配器等於 other.get_allocator()
,則 other
的內部儲存桶陣列會直接轉移到 *this
;否則,插入 other
元素的移動建構副本。如果 已啟用統計資訊,則只有當最終分配器等於 other.get_allocator()
時,才會從 other
轉移內部統計資訊,並且總是呼叫 other.reset_stats()
。
並行性 |
阻塞於 |
訪問
[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)。 |
注意 |
只有當 |
批量訪問
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
才能享受效能提升:超出此大小後,效能預期不會進一步提高。
需求 |
|
傳回 |
訪問的元素數。 |
[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
是常數時,此引用才是常數。執行會根據指定的執行策略語意進行平行處理。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
[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
是常數時,對元素的引用才是常數。
傳回 |
如果 |
平行 [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
是常數時,對元素的引用才是常數。執行會根據指定的執行策略語意進行平行處理。
傳回 |
如果 |
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 平行化表示執行不一定在 |
修改器
emplace
template<class... Args> bool emplace(Args&&... args);
只有當表格中不存在具有等效鍵的元素時,才將使用引數 args
建構的物件插入表格中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 如果 |
複製插入
bool insert(const value_type& obj);
bool insert(const init_type& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 形式為 |
移動插入
bool insert(value_type&& obj);
bool insert(init_type&& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 形式為 |
插入迭代器範圍
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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 在 |
移動 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 在 |
插入迭代器範圍或訪問
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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 在 |
移動 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 在 |
插入迭代器範圍和訪問
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
的現有元素,則將使用 k
和 args
建構的元素插入表中。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此函式類似於 emplace,區別在於如果存在具有等效鍵的元素,則不會建構任何
與 emplace 不同,後者只是將所有參數轉發到 如果發出重新雜湊,則會使指向元素的指標和參考失效。 只有當 |
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
的現有元素,則將使用 k
和 args
建構的元素插入表中。否則,會使用對等效元素的參考來調用 f
;當使用 *_cvisit
多載時,此參考為 const。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果存在具有等效鍵的元素,則不會建構任何
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 只有當 |
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
的現有元素,則將使用 k
和 args
建構的元素插入表中,然後使用對新建立元素的非常數參考來調用 f1
。否則,會使用對等效元素的參考來調用 f2
;當使用 *_cvisit
多載時,此參考為 const。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果存在具有等效鍵的元素,則不會建構任何
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 只有當 |
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)))
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 只有在 |
erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);
如果存在具有與 k
等效鍵的元素,則將其刪除。
傳回 |
刪除的元素數量(0 或 1)。 |
拋出 |
僅在 |
注意 |
只有當 |
依鍵刪除_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)。 |
拋出 |
只有當 |
注意 |
只有當 只有當 |
erase_if
template<class F> size_type erase_if(F f);
使用表格中每個元素的參考來連續調用 f
,並刪除 f
返回 true
的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
只有當 |
平行刪除_if
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
使用表格中每個元素的參考來調用 f
,並刪除 f
返回 true
的元素。根據指定的執行原則語意來平行處理執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。
拋出 |
除非 |
並行性 |
阻塞於 |
清除 (clear)
void clear() noexcept;
刪除表格中的所有元素。
後置條件 |
|
並行性 |
阻塞於 |
合併 (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
中刪除它們。
傳回 |
插入的元素數量。 |
並行性 |
在 |
Map 操作
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指示表格中是否存在鍵等於 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。 |
注意 |
建構、重新雜湊或清除後,表格的最大負載至少為 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
重新雜湊 (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
類似,此函式可用於擴大或縮小表格中的儲存桶數目。
會使指向元素的指標和參考失效,並變更元素的順序。
拋出 |
如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。 |
並行性 |
阻塞於 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
交換
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
。
需求 |
|
並行性 |
在 |
從歸檔載入 concurrent_flat_map
刪除 concurrent_flat_map
x
的所有預先存在的元素,並從歸檔(XML 歸檔)ar
插入儲存到 ar
讀取的儲存中的原始 concurrent_flat_map
other
的元素的還原副本。
需求 |
|
並行性 |
在 |
類別模板 concurrent_flat_set
boost::concurrent_flat_set
— 一個雜湊表,儲存唯一值,並允許並行插入、刪除、查找和存取元素,而無需外部同步機制。
即使它作為一個容器,boost::concurrent_flat_set
並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作(begin
、end
等)。元素存取是透過使用者提供的訪問函式完成,這些函式傳遞給 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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與表格的值類型相同。 |
資料表的元素會保留在內部儲存桶陣列中。元素會插入到由其雜湊碼決定的儲存桶中,但如果儲存桶已佔用 (衝突),則會使用原始位置附近的可用儲存桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或透過呼叫 rehash
/reserve
來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor()
,除了實作可能會決定允許更高載入的小型大小之外。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
並行需求和保證
需要在相同的 Hash
或 Pred
常數執行個體上並行呼叫 operator()
,而不會引入資料競爭。對於 Alloc
為 Allocator
或從 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
一般而言,如果 Hash
、Pred
和 Allocator
這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。
除了銷毀之外,對同一個 concurrent_flat_set
實例上的任何操作的並行調用都不會引入資料競爭 — 也就是說,它們是執行緒安全的。
如果操作 op 被明確指定為阻塞於 x
,其中 x
是 boost::concurrent_flat_set
的實例,則對 x
的先前阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_flat_set
的阻塞操作會依序執行。
如果某個操作僅在發出內部重新雜湊時才阻塞於 x
,則稱該操作阻塞於 x
的重新雜湊。
當由 boost::concurrent_flat_set
在內部執行時,使用者提供的訪問函式對傳遞的元素執行的以下操作不會引入資料競爭
-
對元素的讀取存取。
-
對元素的不可變修改。
-
對元素的可變修改。
-
在接受兩個訪問函數的容器函數中,總是針對第一個函數。
-
在名稱不包含
cvisit
的非常數容器函數中,針對最後一個(或唯一)的訪問函數。
-
任何插入或修改元素 e
的 boost::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
發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。
建構子
預設建構函式
concurrent_flat_set();
使用 hasher()
作為雜湊函數,key_equal()
作為鍵相等謂詞,以及 allocator_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
作為分配器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
concurrent_flat_set(concurrent_flat_set const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
並行性 |
在 |
移動建構函式
concurrent_flat_set(concurrent_flat_set&& other);
移動建構函式。other
的內部桶陣列會直接傳輸到新表格。雜湊函式、謂詞和分配器是從 other
移動建構的。如果 啟用統計資訊,則從 other
傳輸內部統計資訊並呼叫 other.reset_stats()
。
並行性 |
在 |
具有分配器的迭代器範圍建構函式
template<class InputIterator>
concurrent_flat_set(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
concurrent_flat_set(concurrent_flat_set const& other, Allocator const& a);
建構一個表格,複製 other
包含的元素、雜湊函數和謂詞,但使用分配器 a
。
並行性 |
在 |
具備配置器的移動建構子
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()
。
並行性 |
在 |
從 unordered_flat_set 移動建構函式
concurrent_flat_set(unordered_flat_set<Key, Hash, Pred, Allocator>&& other);
從 unordered_flat_set
移動建構。other
的內部桶陣列會直接傳輸到新的容器。雜湊函式、謂詞和分配器是從 other
移動建構的。如果 啟用統計資訊,則從 other
傳輸內部統計資訊並呼叫 other.reset_stats()
。
複雜度 |
O( |
初始化列表建構子
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
的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
concurrent_flat_set(size_type n, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
concurrent_flat_set(size_type n, hasher const& hf, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
concurrent_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l)
的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
以及預設雜湊函數和鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_flat_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,a
作為分配器,以及預設鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
賦值
複製賦值
concurrent_flat_set& operator=(concurrent_flat_set const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動賦值運算子。銷毀先前存在的元素,從 other
交換雜湊函式和謂詞,並從 other
移動賦值分配器(如果存在 Alloc::propagate_on_container_move_assignment
且 Alloc::propagate_on_container_move_assignment::value
為 true
)。如果在這一點上分配器等於 other.get_allocator()
,則 other
的內部桶陣列會直接傳輸到 *this
;否則,插入 other
元素的移動建構副本。如果 啟用統計資訊,則僅當最終分配器等於 other.get_allocator()
時才從 other
傳輸內部統計資訊,並始終呼叫 other.reset_stats()
。
並行性 |
阻塞於 |
訪問
[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)。 |
注意 |
只有當 |
批量訪問
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
才能獲得效能提升:超過此大小,預期效能不會進一步提高。
需求 |
|
傳回 |
訪問的元素數。 |
[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
。根據指定的執行策略的語義進行平行化執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
[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
或訪問完所有元素。
傳回 |
如果 |
平行 [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
或訪問完所有元素。根據指定的執行策略的語義進行平行化執行。
傳回 |
如果 |
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 平行化表示執行不一定在 |
修改器
emplace
template<class... Args> bool emplace(Args&&... args);
只有當表格中不存在具有等效鍵的元素時,才將使用引數 args
建構的物件插入表格中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
複製插入
bool insert(const value_type& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
移動插入
bool insert(value_type&& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
透明插入
template<class K> bool insert(K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 僅當 |
插入迭代器範圍
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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
移動 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
透明 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 僅當 |
插入迭代器範圍或訪問
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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
移動 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 |
透明 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果發出重新雜湊,則會使指向元素的指標和參考失效。 僅當 |
插入迭代器範圍和訪問
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)。 |
拋出 |
僅在 |
注意 |
只有當 |
依鍵刪除_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)。 |
拋出 |
只有當 |
注意 |
只有當 只有當 |
erase_if
template<class F> size_type erase_if(F f);
使用表格中每個元素的參考來連續調用 f
,並刪除 f
返回 true
的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
只有當 |
平行刪除_if
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
使用表格中每個元素的參考來調用 f
,並刪除 f
返回 true
的元素。根據指定的執行原則語意來平行處理執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。
拋出 |
除非 |
並行性 |
阻塞於 |
清除 (clear)
void clear() noexcept;
刪除表格中的所有元素。
後置條件 |
|
並行性 |
阻塞於 |
合併 (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
中刪除它們。
傳回 |
插入的元素數量。 |
並行性 |
在 |
Set 操作
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指示表格中是否存在鍵等於 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。 |
注意 |
建構、重新雜湊或清除後,表格的最大負載至少為 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
重新雜湊 (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
類似,此函式可用於擴大或縮小表格中的儲存桶數目。
會使指向元素的指標和參考失效,並變更元素的順序。
拋出 |
如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。 |
並行性 |
阻塞於 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
交換
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
。
需求 |
|
並行性 |
在 |
從歸檔載入 concurrent_flat_set
刪除 concurrent_flat_set
x
的所有先前存在的元素,並從歸檔(XML 歸檔)ar
插入儲存到 ar
讀取的儲存區的原始 concurrent_flat_set
other
的還原副本。
需求 |
|
並行性 |
在 |
類別模板 concurrent_node_map
boost::concurrent_node_map
— 一個基於節點的雜湊表,將唯一鍵與另一個值關聯,並允許並行插入、刪除、查找和存取元素,而無需外部同步機制。
即使它作為一個容器,boost::concurrent_node_map
並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作(begin
、end
等)。元素存取和修改是透過使用者提供的訪問函式完成,這些函式傳遞給 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>>>; } }
描述
樣板參數
鍵 |
|
T |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
配置器的值類型與資料表的值類型相同。支援使用 花俏指標的配置器。 |
表格的元素節點保留在一個內部桶陣列中。節點會插入由其元素雜湊碼決定的桶中,但如果該桶已被佔用(衝突),則會使用原始位置附近的可用桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或透過呼叫 rehash
/reserve
來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor()
,除了實作可能會決定允許更高載入的小型大小之外。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
並行需求和保證
需要在相同的 Hash
或 Pred
常數執行個體上並行呼叫 operator()
,而不會引入資料競爭。對於 Alloc
為 Allocator
或從 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
一般而言,如果 Hash
、Pred
和 Allocator
這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。
除了銷毀之外,對同一個 concurrent_node_map
實例上的任何操作的並行調用都不會引入資料競爭 — 也就是說,它們是執行緒安全的。
如果操作 op 被明確指定為阻塞於 x
,其中 x
是 boost::concurrent_node_map
的實例,則對 x
的先前阻塞操作會與 op 同步。因此,在多執行緒情境中,對同一個 concurrent_node_map
的阻塞操作會依序執行。
如果某個操作僅在發出內部重新雜湊時才阻塞於 x
,則稱該操作阻塞於 x
的重新雜湊。
當由 boost::concurrent_node_map
在內部執行時,使用者提供的訪問函式對傳遞的元素執行的以下操作不會引入資料競爭
-
對元素的讀取存取。
-
對元素的不可變修改。
-
對元素的可變修改。
-
在接受兩個訪問函數的容器函數中,總是針對第一個函數。
-
在名稱不包含
cvisit
的非常數容器函數中,針對最後一個(或唯一)的訪問函數。
-
任何插入或修改元素 e
的 boost::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
發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。
型別定義
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
。
建構子
預設建構函式
concurrent_node_map();
使用 hasher()
作為雜湊函數,key_equal()
作為鍵相等謂詞,以及 allocator_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
作為分配器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
concurrent_node_map(concurrent_node_map const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
並行性 |
在 |
移動建構函式
concurrent_node_map(concurrent_node_map&& other);
移動建構函式。other
的內部桶陣列會直接傳輸到新表格。雜湊函式、謂詞和分配器是從 other
移動建構的。如果 啟用統計資訊,則從 other
傳輸內部統計資訊並呼叫 other.reset_stats()
。
並行性 |
在 |
具有分配器的迭代器範圍建構函式
template<class InputIterator>
concurrent_node_map(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
concurrent_node_map(concurrent_node_map const& other, Allocator const& a);
建構一個表格,複製 other
包含的元素、雜湊函數和謂詞,但使用分配器 a
。
並行性 |
在 |
具備配置器的移動建構子
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()
。
並行性 |
在 |
從 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( |
初始化列表建構子
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
的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
concurrent_node_map(size_type n, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
concurrent_node_map(size_type n, hasher const& hf, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
concurrent_node_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l)
的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
以及預設雜湊函數和鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_node_map(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,a
作為分配器,以及預設鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
賦值
複製賦值
concurrent_node_map& operator=(concurrent_node_map const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動賦值運算子。會銷毀先前存在的元素,交換來自 other
的雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則會從 other
移動賦值配置器。如果在這一點上配置器等於 other.get_allocator()
,則 other
的內部 bucket 陣列會直接轉移到 *this
;否則,會插入 other
元素的移動建構副本。如果 啟用統計資訊,則當最終配置器等於 other.get_allocator()
時,會轉移來自 other
的內部統計資訊,並總是呼叫 other.reset_stats()
。
並行性 |
阻塞於 |
訪問
[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)。 |
注意 |
只有當 |
批量訪問
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
以享受效能提升:超過此大小,預計效能不會進一步提高。
需求 |
|
傳回 |
訪問的元素數。 |
[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
是常數時,此引用才是常數。執行會根據指定的執行策略語意進行平行處理。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
[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
是常數時,對元素的引用才是常數。
傳回 |
如果 |
平行 [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
是常數時,對元素的引用才是常數。執行會根據指定的執行策略語意進行平行處理。
傳回 |
如果 |
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 平行化表示執行不一定在 |
修改器
emplace
template<class... Args> bool emplace(Args&&... args);
只有當表格中不存在具有等效鍵的元素時,才將使用引數 args
建構的物件插入表格中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果 |
複製插入
bool insert(const value_type& obj);
bool insert(const init_type& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
形式為 |
移動插入
bool insert(value_type&& obj);
bool insert(init_type&& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
形式為 |
插入迭代器範圍
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
為空。
傳回 |
從
|
拋出 |
如果因呼叫 |
並行性 |
在 |
注意 |
如果 |
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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
在 |
移動 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
在 |
插入迭代器範圍或訪問
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。
傳回 |
從
|
拋出 |
如果除了呼叫 |
並行性 |
在 |
注意 |
如果 |
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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
在 |
移動 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。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
在 |
插入迭代器範圍和訪問
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。
傳回 |
從
|
拋出 |
如果除了呼叫 |
並行性 |
在 |
注意 |
如果 |
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
的現有元素,則將使用 k
和 args
建構的元素插入表中。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此函式與 emplace 類似,不同之處在於,如果存在具有等效鍵的元素,則不會建構
與 emplace 不同,後者只是將所有引數轉送到 只有當 |
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
的現有元素,則將使用 k
和 args
建構的元素插入表中。否則,會使用對等效元素的參考來調用 f
;當使用 *_cvisit
多載時,此參考為 const。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果存在具有等效鍵的元素,則不會建構任何
此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 只有當 |
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
的現有元素,則將使用 k
和 args
建構的元素插入表中,然後使用對新建立元素的非常數參考來調用 f1
。否則,會使用對等效元素的參考來調用 f2
;當使用 *_cvisit
多載時,此參考為 const。
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
如果存在具有等效鍵的元素,則不會建構任何
介面僅供展示,因為 C++ 不允許在可變引數包之後宣告參數 只有當 |
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)))
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
只有在 |
erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);
如果存在具有與 k
等效鍵的元素,則將其刪除。
傳回 |
刪除的元素數量(0 或 1)。 |
拋出 |
僅在 |
注意 |
只有當 |
依鍵刪除_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)。 |
拋出 |
只有當 |
注意 |
只有當 只有當 |
erase_if
template<class F> size_type erase_if(F f);
使用表格中每個元素的參考來連續調用 f
,並刪除 f
返回 true
的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
只有當 |
平行刪除_if
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
使用表格中每個元素的參考來調用 f
,並刪除 f
返回 true
的元素。根據指定的執行原則語意來平行處理執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。
拋出 |
除非 |
並行性 |
阻塞於 |
提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
提取具有與 k
等效鍵的元素(如果存在)。
傳回 |
一個包含提取元素的 |
拋出 |
僅在 |
注意 |
只有當 |
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
。
傳回 |
一個包含提取元素的 |
拋出 |
僅當 |
注意 |
只有當 |
清除 (clear)
void clear() noexcept;
刪除表格中的所有元素。
後置條件 |
|
並行性 |
阻塞於 |
合併 (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
中刪除它們。
傳回 |
插入的元素數量。 |
並行性 |
在 |
Map 操作
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指示表格中是否存在鍵等於 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。 |
注意 |
建構、重新雜湊或清除後,表格的最大負載至少為 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
重新雜湊 (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
類似,此函式可用於擴大或縮小表格中的儲存桶數目。
拋出 |
如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。 |
並行性 |
阻塞於 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
交換
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
。
需求 |
|
並行性 |
在 |
從封存載入 concurrent_node_map
刪除 concurrent_node_map
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入已還原的原始 concurrent_node_map
other
的元素副本,這些副本已儲存到 ar
讀取的儲存空間。
需求 |
|
並行性 |
在 |
類別模板 concurrent_node_set
boost::concurrent_node_set
— 一個基於節點的雜湊表,用於儲存唯一值,並允許並行元素插入、刪除、查找和存取,而無需外部同步機制。
儘管它充當容器,但 boost::concurrent_node_set
並不符合標準 C++ 容器概念。特別是,不提供迭代器和相關操作 (begin
、end
等)。元素存取是透過使用者提供的訪問函式來完成,這些函式會傳遞到 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>>; } }
描述
樣板參數
鍵 |
|
雜湊 |
一個一元函數物件類型,作為 |
Pred |
一個二元函數物件,在 |
分配器 |
一個分配器,其值類型與表格的值類型相同。 |
表格的元素節點保留在一個內部桶陣列中。節點會插入由其元素雜湊碼決定的桶中,但如果該桶已被佔用(衝突),則會使用原始位置附近的可用桶。
儲存桶陣列的大小可以透過呼叫 insert
/emplace
自動增加,或透過呼叫 rehash
/reserve
來增加。資料表的載入係數 (元素數量除以儲存桶數量) 永遠不大於 max_load_factor()
,除了實作可能會決定允許更高載入的小型大小之外。
如果 hash_is_avalanching<Hash>::value
為 true
,則雜湊函數會按原樣使用;否則,會新增一個位混合後處理階段,以提高雜湊品質,但會增加額外的計算成本。
並行需求和保證
需要在相同的 Hash
或 Pred
常數執行個體上並行呼叫 operator()
,而不會引入資料競爭。對於 Alloc
為 Allocator
或從 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
一般而言,如果 Hash
、Pred
和 Allocator
這些類型不具有狀態,或者如果這些操作只涉及對內部資料成員的常數存取,那麼它們的要求就會被滿足。
除了銷毀之外,並行調用 concurrent_node_set
同一執行個體上的任何操作都不會引入資料競爭 — 也就是說,它們是執行緒安全的。
如果操作 op 明確指定為封鎖 x
,其中 x
是 boost::concurrent_node_set
的執行個體,則先前對 x
的封鎖操作會與 op 同步。因此,在多執行緒情境中,對同一 concurrent_node_set
的封鎖操作會循序執行。
如果某個操作僅在發出內部重新雜湊時才阻塞於 x
,則稱該操作阻塞於 x
的重新雜湊。
當由 boost::concurrent_node_set
內部執行時,使用者提供的訪問函式在傳遞的元素上執行以下操作不會引入資料競爭
-
對元素的讀取存取。
-
對元素的不可變修改。
-
對元素的可變修改。
-
在接受兩個訪問函數的容器函數中,總是針對第一個函數。
-
在名稱不包含
cvisit
的非常數容器函數中,針對最後一個(或唯一)的訪問函數。
-
任何插入或修改元素 e
的 boost::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
發出訊號。當執行速度是一個問題時,可以透過全域定義此巨集來停用此功能。
型別定義
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
。
建構子
預設建構函式
concurrent_node_set();
使用 hasher()
作為雜湊函數,key_equal()
作為鍵相等謂詞,以及 allocator_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
作為分配器。
後置條件 |
|
需求 |
如果使用預設值,則 |
迭代器範圍建構函式
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)
的元素插入其中。
需求 |
如果使用預設值,則 |
複製建構函式
concurrent_node_set(concurrent_node_set const& other);
複製建構子。複製包含的元素、雜湊函數、述詞和配置器。
如果 Allocator::select_on_container_copy_construction
存在並具有正確的簽章,則分配器將從其結果中建構。
需求 |
|
並行性 |
在 |
移動建構函式
concurrent_node_set(concurrent_node_set&& other);
移動建構函式。other
的內部 bucket 陣列會直接轉移到新表格。雜湊函式、述詞和配置器會從 other
移動建構而來。如果 啟用統計資訊,則會轉移來自 other
的內部統計資訊,並呼叫 other.reset_stats()
。
並行性 |
在 |
具有分配器的迭代器範圍建構函式
template<class InputIterator>
concurrent_node_set(InputIterator f, InputIterator l, const allocator_type& a);
使用 a
作為分配器,使用預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 [f, l)
的元素插入其中。
需求 |
|
具有分配器的複製建構函式
concurrent_node_set(concurrent_node_set const& other, Allocator const& a);
建構一個表格,複製 other
包含的元素、雜湊函數和謂詞,但使用分配器 a
。
並行性 |
在 |
具備配置器的移動建構子
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()
。
並行性 |
在 |
從 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( |
初始化列表建構子
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
的元素插入其中。
需求 |
如果使用預設值,則 |
具備配置器的儲存桶計數建構子
concurrent_node_set(size_type n, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設雜湊函數和鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備雜湊函數和配置器的儲存桶計數建構子
concurrent_node_set(size_type n, hasher const& hf, allocator_type const& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,預設鍵相等謂詞,以及 a
作為分配器。
後置條件 |
|
需求 |
|
具備儲存桶計數和配置器的迭代器範圍建構子
template<class InputIterator>
concurrent_node_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
作為分配器,以及預設雜湊函數和鍵相等謂詞,並將來自 [f, l)
的元素插入其中。
需求 |
|
具備儲存桶計數和雜湊函數的迭代器範圍建構子
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)
的元素插入其中。
需求 |
|
具備配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, const allocator_type& a);
使用 a
以及預設雜湊函數和鍵相等謂詞,建構一個空表格,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數和配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, size_type n, const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 a
以及預設雜湊函數和鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
具備儲存桶計數、雜湊函數和配置器的初始化列表建構子
concurrent_node_set(std::initializer_list<value_type> il, size_type n, const hasher& hf,
const allocator_type& a);
建構一個至少有 n
個儲存桶的空表格,使用 hf
作為雜湊函數,a
作為分配器,以及預設鍵相等謂詞,並將來自 il
的元素插入其中。
需求 |
|
賦值
複製賦值
concurrent_node_set& operator=(concurrent_node_set const& other);
賦值運算子。銷毀先前存在的元素,從 other
複製賦值雜湊函數和述詞,如果存在 Alloc::propagate_on_container_copy_assignment
且 Alloc::propagate_on_container_copy_assignment::value
為 true
,則從 other
複製賦值配置器,最後插入 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);
移動賦值運算子。會銷毀先前存在的元素,交換來自 other
的雜湊函式和述詞,並且如果 Alloc::propagate_on_container_move_assignment
存在且 Alloc::propagate_on_container_move_assignment::value
為 true
,則會從 other
移動賦值配置器。如果在這一點上配置器等於 other.get_allocator()
,則 other
的內部 bucket 陣列會直接轉移到 *this
;否則,會插入 other
元素的移動建構副本。如果 啟用統計資訊,則當最終配置器等於 other.get_allocator()
時,會轉移來自 other
的內部統計資訊,並總是呼叫 other.reset_stats()
。
並行性 |
阻塞於 |
訪問
[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)。 |
注意 |
只有當 |
批量訪問
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
以享受效能提升:超過此大小,預計效能不會進一步提高。
需求 |
|
傳回 |
訪問的元素數。 |
[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
。根據指定的執行策略的語義進行平行化執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
[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
或訪問完所有元素。
傳回 |
如果 |
平行 [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
或訪問完所有元素。根據指定的執行策略的語義進行平行化執行。
傳回 |
如果 |
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 平行化表示執行不一定在 |
修改器
emplace
template<class... Args> bool emplace(Args&&... args);
只有當表格中不存在具有等效鍵的元素時,才將使用引數 args
建構的物件插入表格中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
複製插入
bool insert(const value_type& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
移動插入
bool insert(value_type&& obj);
當且僅當表中沒有具有等效鍵的元素時,才將 obj
插入表中。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
透明插入
template<class K> bool insert(K&& k);
如果容器中沒有具有等效鍵的元素,則在容器中插入一個從 std::forward<K>(k)
建構的元素。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
僅當 |
插入迭代器範圍
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
為空。
傳回 |
從
|
拋出 |
如果因呼叫 |
並行性 |
在 |
注意 |
如果 |
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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
移動 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
透明 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
僅當 |
插入迭代器範圍或訪問
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
。
傳回 |
從
|
拋出 |
如果除了呼叫 |
並行性 |
在 |
注意 |
如果 |
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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
此介面僅用於說明,因為 C++ 不允許在可變參數包之後宣告參數 |
複製 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
移動 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
透明 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
。
需求 |
|
傳回 |
如果進行了插入,則為 |
並行性 |
在 |
注意 |
僅當 |
插入迭代器範圍和訪問
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
。
傳回 |
從
|
拋出 |
如果除了呼叫 |
並行性 |
在 |
注意 |
如果 |
erase
size_type erase(const key_type& k);
template<class K> size_type erase(const K& k);
如果存在具有與 k
等效鍵的元素,則將其刪除。
傳回 |
刪除的元素數量(0 或 1)。 |
拋出 |
僅在 |
注意 |
只有當 |
依鍵刪除_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)。 |
拋出 |
只有當 |
注意 |
只有當 只有當 |
erase_if
template<class F> size_type erase_if(F f);
使用表格中每個元素的參考來連續調用 f
,並刪除 f
返回 true
的元素。
傳回 |
已刪除的元素數量。 |
拋出 |
只有當 |
平行刪除_if
template<class ExecutionPolicy, class F> void erase_if(ExecutionPolicy&& policy, F f);
使用表格中每個元素的參考來調用 f
,並刪除 f
返回 true
的元素。根據指定的執行原則語意來平行處理執行。
拋出 |
根據所使用執行策略的例外處理機制,如果 |
注意 |
僅在支援 C++17 平行演算法的編譯器中可用。 只有當 不允許未排序的執行策略。 |
交換 (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_swap
且 Allocator::propagate_on_container_swap::value
為 true
,則會交換表格的配置器。否則,與不等配置器交換會導致未定義的行為。
拋出 |
除非 |
並行性 |
阻塞於 |
提取
node_type extract(const key_type& k);
template<class K> node_type extract(K&& k);
提取具有與 k
等效鍵的元素(如果存在)。
傳回 |
一個包含提取元素的 |
拋出 |
僅在 |
注意 |
只有當 |
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
。
傳回 |
一個包含提取元素的 |
拋出 |
僅當 |
注意 |
只有當 |
清除 (clear)
void clear() noexcept;
刪除表格中的所有元素。
後置條件 |
|
並行性 |
阻塞於 |
合併 (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
中刪除它們。
傳回 |
插入的元素數量。 |
並行性 |
在 |
Set 操作
計數 (count)
size_type count(const key_type& k) const;
template<class K>
size_type count(const K& k) const;
傳回 |
具有與 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
包含 (contains)
bool contains(const key_type& k) const;
template<class K>
bool contains(const K& k) const;
傳回 |
一個布林值,指示表格中是否存在鍵等於 |
注意 |
只有當 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
雜湊策略
載入因子 (load_factor)
float load_factor() const noexcept;
傳回 |
|
max_load
size_type max_load() const noexcept;
傳回 |
在不進行重新雜湊的情況下,表格可容納的最大元素數量,假設不會再刪除其他元素。 |
注意 |
建構、重新雜湊或清除後,表格的最大負載至少為 在存在並行插入操作的情況下,傳回的值可能無法準確反映執行後表格的真實狀態。 |
重新雜湊 (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
類似,此函式可用於擴大或縮小表格中的儲存桶數目。
拋出 |
如果擲回例外,則此函式無效,除非是由表格的雜湊函式或比較函式擲回例外。 |
並行性 |
阻塞於 |
推導指引
如果符合下列任何一項,則推導指南不會參與多載解析
-
它具有
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
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
。
並行性 |
在 |
注意 |
如果兩個表格沒有等效的相等謂詞,則行為未定義。 |
交換
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
。
需求 |
|
並行性 |
在 |
從封存載入 concurrent_node_set
刪除 concurrent_node_set
x
的所有先前存在的元素,並從封存 (XML 封存) ar
插入已還原的原始 concurrent_node_set
other
的元素副本,這些副本已儲存到 ar
讀取的儲存空間。
需求 |
|
並行性 |
在 |
變更日誌
版本 1.87.0 - 重大更新
-
新增了並行、基於節點的容器
boost::concurrent_node_map
和boost::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]visit
的std::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
常數設定為true
的is_avalanching
typedef 標記(通常,將is_avalanching
定義為std::true_type
)。using is_avalanching = void
已被棄用,但為了向後相容性而允許使用。 -
為容器和迭代器新增了 Visual Studio Natvis 框架自訂視覺化。這適用於所有使用原始指標的配置器容器。在此版本中,如果容器的配置器使用花式指標,則不支援這些容器和迭代器。這可能會在後續版本中解決。
版本 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]set
和boost::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_map
和boost::unordered_node_set
。 -
依照 P2363 中指定,將異質查找擴展到更多成員函數。
-
將開放定址容器的先前後混合處理替換為基於常數擴展乘法的新演算法。
-
修正了內部 emplace() 實作中的錯誤,其中堆疊本地類型未使用容器的配置器正確建構,這會破壞 uses-allocator 建構。
版本 1.81.0 - 重大更新
-
新增了基於開放定址的快速容器
boost::unordered_flat_map
和boost::unordered_flat_set
。 -
為所有容器新增了 CTAD 推導指南。
-
新增了 LWG 問題 2713 中指定的遺失建構子。
版本 1.80.0 - 重大更新
-
重構內部實作以大幅提高速度
-
允許
final
Hasher 和 KeyEqual 物件 -
更新文件,新增基準圖表和關於新內部資料結構的註解
版本 1.79.0
-
改進了 C++20 支援
-
所有容器都已更新以支援異質
count
、equal_range
和find
。 -
所有容器現在都實作了成員函數
contains
。 -
已為所有容器實作
erase_if
。
-
-
改進了 C++23 支援
-
所有容器都已更新以支援異質
erase
和extract
。
-
-
將
reserve
的行為變更為預先配置 (PR#59)。 -
測試套件中的各種警告修正。
-
更新程式碼以在內部使用
boost::allocator_traits
。 -
切換到費波那契雜湊。
-
更新文件,以 AsciiDoc 而非 QuickBook 撰寫。
版本 1.67.0
-
改進了 C++17 支援
-
從標準新增範本推導指南。
-
在節點控制代碼中使用
optional
的簡單實作,使其更接近標準。 -
將遺失的
noexcept
規範新增至swap
、operator=
和節點控制代碼,並變更實作以符合。在實作中使用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.65.0
-
將已棄用的屬性新增至
quick_erase
和erase_return_void
。這次我真的會在未來的版本中移除它們。 -
小標準合規性修正
-
swap
自由函數的noexpect
規格。 -
新增遺失的
insert(P&&)
方法。
-
版本 1.64.0
-
在
unordered_map
中初步支援新的 C++17 成員函數:insert_or_assign
和try_emplace
。 -
初步支援
merge
和extract
。尚不包括在unordered_map
和unordered_multimap
之間或在unordered_set
和unordered_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_multiset
和unordered_multimap
的異常安全問題。可能會稍微慢一點。 -
停止使用一些舊編譯器有問題的傳回值 SFINAE。
版本 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.50.0
-
修正
unordered_multiset
和unordered_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_erase
和 erase_return_void
,它們將在未來的版本中移除。
C++11 的支援導致了一些破壞性變更
-
相等性比較已變更為 C++11 規格。在具有相等鍵的容器中,過去具有相等鍵的群組中的元素必須具有相同的順序才能被視為相等,現在它們可以是彼此的排列組合。若要使用舊的行為,請定義巨集
BOOST_UNORDERED_DEPRECATED_EQUALITY
。 -
當要交換的兩個容器具有不相等的配置器時,swap 的行為會有所不同。它過去會使用適當的配置器來配置新的節點,現在如果配置器具有成員結構
propagate_on_container_swap
,使得propagate_on_container_swap::value
為 true,它會交換配置器。 -
配置器的
construct
和destroy
函式會使用原始指標呼叫,而不是配置器的pointer
類型。 -
emplace
過去會模擬早期 C++0x 草稿中出現的可變參數 pair 建構函式。由於它們已被移除,因此不再這樣做。它確實會模擬新的piecewise_construct
pair 建構函式 - 只是您需要使用boost::piecewise_construct
。若要使用舊的可變參數建構函式模擬,請定義BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT
。
版本 1.45.0
-
修正使用傳回複製
value_type
的迭代器插入unordered_map
或unordered_set
時的錯誤。
版本 1.43.0
-
工單 3966:
erase_return_void
現在是quick_erase
,這是目前解決迭代器刪除速度慢問題的先驅,儘管這在未來很有可能會變更。舊的方法名稱仍保留以確保向後相容性,但被視為已棄用,並將在未來的版本中移除。 -
使用 Boost.Exception。
-
停止使用已棄用的
BOOST_HAS_*
巨集。
版本 1.41.0 - 重大更新
-
原始版本大量使用巨集來規避一些舊編譯器對範本支援不佳的問題。但由於我不再支援這些編譯器,且巨集的使用開始成為維護負擔,因此已將其實作類別重寫為使用範本而非巨集。
-
由於使用
boost::compressed_pair
進行 EBO 和略有不同的函式緩衝區(現在使用布林值而不是成員指標),因此容器物件現在更小。 -
桶是延遲配置的,這表示建構一個空容器不會配置任何記憶體。
版本 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 日進行的審查。
參考文獻
-
C/C++ Users Journal。2006 年 2 月。Pete Becker。STL 和 TR1:第三部分 - 無序容器。
標準無序容器簡介。 -
Wikipedia。雜湊表。
雜湊表實作簡介。討論了封閉定址和開放定址方法之間的差異。 -
Peter Dimov,2022 年。Boost.Unordered 的開發計畫。
著作權和許可
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)