class template
std::flat_map(C++23)
namespace std {
template <class Key,
class T,
class Compare = less<Key>,
class KeyContainer = vector<Key>,
class MappedContainer = vector<T>>
class flat_map;
}
概要
std::flat_map
は、重複しない要素を格納する連想コンテナの一種であり、キーとそれに対応する値を格納する。
std::flat_map
は、ノードベースで実装されるstd::map
、ハッシュテーブルで実装されるstd::unordered_map
とは異なり、ソート済み配列と二分探索の組み合わせで実装される。これはほかの実装と比較して、メモリ使用量と列挙速度において優位であり、一方で挿入速度と検索速度はほかの実装に劣る。
また、このクラスは分類としてはstd::queue
やstd::skack
と同様のコンテナアダプタに分類され、キーの配列と値の配列の2つを内部で持ち、それをstd::ranges::zip_view
で綴じあわせて扱う実装となっている。
このコンテナクラスは、ランダムアクセスイテレータをサポートする。
ほかの連想コンテナとの要件の違い
このクラスは要件として、コンテナクラスと、逆順コンテナクラスであることは満たすが、連想コンテナの要件としては以下を満たさない:
- node handleに関する要件
- イテレータ無効化に関する要件
- 単一要素の挿入と削除に線形時間かかる (挿入位置のイテレータを指定したとしても)
また、このコンテナはメモリアロケータを指定できない設計にもなっている。
value_type
は、std::map
ではstd::pair<const Key, T>
だが、このクラスはstd::pair<Key, T>
である (const
がつかない)。
以下の不変条件をもち、メンバ関数のいずれかが例外によって終了した場合には不変条件の状態に復元される (ただし、その復元操作によってコンテナが空になる可能性がある):
- キーの配列と値の配列が、同じ要素数をもつ
- キーの配列が、指定された比較関数オブジェクトを尊重してソートを行う
- 値の配列内のオフセット
off
の値は、キー配列内のオフセットoff
のキーに関連付けられた値である
KeyContainer
とMappedContainer
に指定するコンテナ型は、
- シーケンスコンテナの要件を満たし、
- ランダムアクセスイテレータをもち、
- 例外を送出しないメンバ関数
size()
とmax_size()
をもつこと
Key
がKeyContainer::value_type
と同じ型であること
T
がMappedContainer::value_type
と同じ型であること
メンバ関数
構築・破棄
イテレータ
名前 |
説明 |
対応バージョン |
begin |
先頭を指すイテレータを取得する |
C++23 |
cbegin |
先頭を指す読み取り専用イテレータを取得する |
C++23 |
end |
末尾の次を指すイテレータを取得する |
C++23 |
cend |
末尾の次を指す読み取り専用イテレータを取得する |
C++23 |
rbegin |
末尾を指す逆イテレータを取得する |
C++23 |
crbegin |
末尾を指す読み取り専用逆イテレータを取得する |
C++23 |
rend |
先頭の前を指す逆イテレータを取得する |
C++23 |
crend |
先頭の前を指す読み取り専用逆イテレータを取得する |
C++23 |
領域
名前 |
説明 |
対応バージョン |
empty |
コンテナが空であるかどうかを調べる |
C++23 |
size |
要素数を取得する |
C++23 |
max_size |
格納可能な最大の要素数を取得する |
C++23 |
コンテナの変更
要素アクセス
オブザーバー
メンバ型
名前 |
説明 |
対応バージョン |
key_type |
キーの型。テンプレートパラメータ Key |
C++23 |
mapped_type |
値の型。テンプレートパラメータ T |
C++23 |
value_type |
要素の型。std::pair<key_type, mapped_type> |
C++23 |
key_compare |
キー値の大小関係を判定する二項述語の型。テンプレートパラメータ Compare |
C++23 |
value_compare |
要素値のキー部分で大小関係を判定する二項述語の型。入れ子クラス |
C++23 |
reference |
要素への参照型。std::pair<const key_type&, mapped_type&> |
C++23 |
const_reference |
要素へのconst 参照型。std::pair<const key_type&, const mapped_type&> |
C++23 |
size_type |
要素数を表す符号なし整数型 size_t |
C++23 |
difference_type |
同一のコンテナを指す iterator の差を表す符号付き整数型 ptrdiff_t |
C++23 |
iterator |
ランダムアクセスイテレータ |
C++23 |
const_iterator |
読み取り専用ランダムアクセスイテレータ |
C++23 |
reverse_iterator |
逆順ランダムアクセスイテレータ。std::reverse_iterator<iterator> |
C++23 |
const_reverse_iterator |
読み取り専用逆順ランダムアクセスイテレータ。std::reverse_iterator<const_iterator> |
C++23 |
key_container_type |
キーを格納するコンテナ型 KeyContainer |
C++23 |
mapped_container_type |
値を格納するコンテナ型 MappedContainer |
C++23 |
containers |
キーのコンテナと値のコンテナを保持する型 |
C++23 |
key_equiv |
要素をとってキーの等価比較を行う説明専用の関数オブジェクト |
C++23 |
非メンバ関数
要素削除
名前 |
説明 |
対応バージョン |
erase_if |
指定した条件に合致する要素とその分の領域を、コンテナから削除する |
C++23 |
非メンバ(Hidden friends)関数
比較演算子
名前 |
説明 |
対応バージョン |
operator== |
左辺と右辺が等しいかの判定を行う |
C++23 |
bool operator!=(const flat_map& x, const flat_map& y); |
左辺と右辺が等しくないかの判定を行う (== により使用可能) |
C++23 |
operator<=> |
三方比較を行う |
C++23 |
bool operator<(const flat_map& x, const flat_map& y); |
左辺が右辺より小さいかの判定を行う (<=> により使用可能) |
C++23 |
bool operator<=(const flat_map& x, const flat_map& y); |
左辺が右辺より小さいか等しいかの判定を行う (<=> により使用可能) |
C++23 |
bool operator>(const flat_map& x, const flat_map& y); |
左辺が右辺より大きいかの判定を行う (<=> により使用可能) |
C++23 |
bool operator>=(const flat_map& x, const flat_map& y); |
左辺が右辺より大きいか等しいかの判定を行う (<=> により使用可能) |
C++23 |
入れ替え
名前 |
説明 |
対応バージョン |
swap |
2つのflat_map オブジェクトを入れ替える |
C++23 |
推論補助
その他
例
基本的な使い方
出力
3
Alice : 3
Bob : 1
Carol : 4
ユーザー定義型をキーとして使用する (operator<=>
を定義)
#include <iostream>
#include <string>
#include <flat_map>
// 要素がひとつの場合
struct MyInt {
int value;
friend auto operator<=>(const MyInt& a, const MyInt& b) noexcept {
return a.value <=> b.value;
}
};
// 要素が複数の場合
struct Person {
int id;
int age;
std::string name;
friend auto operator<=>(const Person& a, const Person& b) noexcept {
if (auto comp = a.id <=> b.id; comp != 0) {
return comp;
}
if (auto comp = a.age <=> b.age; comp != 0) {
return comp;
}
return a.name <=> b.name;
}
};
int main()
{
std::flat_map<MyInt, int> fm1 {
{MyInt{1}, 3},
{MyInt{2}, 1},
{MyInt{3}, 4},
};
std::cout << fm1[MyInt{2}] << std::endl;
std::flat_map<Person, int> fm2 {
{Person{1, 18, "Alice"}, 3},
{Person{2, 30, "Bob"}, 1},
{Person{3, 30, "Carol"}, 4},
};
std::cout << fm2[Person{2, 30, "Bob"}] << std::endl;
}
出力
1
1
ユーザー定義型をキーとして使用する (大小比較の関数オブジェクトを定義)
#include <iostream>
#include <string>
#include <tuple>
#include <flat_map>
// 要素がひとつの場合
struct MyInt {
int value;
};
struct MyIntLess {
bool operator()(const MyInt& a, const MyInt& b) const noexcept {
return a.value < b.value;
}
};
// 要素が複数の場合
struct Person {
int id;
int age;
std::string name;
};
struct PersonLess {
bool operator()(const Person& a, const Person& b) const noexcept {
// キーとして比較したい要素を列挙する
return std::tie(a.id, a.age, a.name) < std::tie(b.id, b.age, b.name);
}
};
int main()
{
std::flat_map<MyInt, int, MyIntLess> fm1 {
{MyInt{1}, 3},
{MyInt{2}, 1},
{MyInt{3}, 4},
};
std::cout << fm1[MyInt{2}] << std::endl;
std::flat_map<Person, int, PersonLess> fm2 {
{Person{1, 18, "Alice"}, 3},
{Person{2, 30, "Bob"}, 1},
{Person{3, 30, "Carol"}, 4},
};
std::cout << fm2[Person{2, 30, "Bob"}] << std::endl;
}
出力
1
1
バージョン
言語
処理系
参照