namespace std {
class any;
}
概要
any
クラスは、コピー可能なあらゆる型の値を保持できる記憶域型である。保持する値と型は動的に切り替えることができる。
std::any x = 3; // int型の値3で初期化
x = std::string("Hello"); // std::string型の値"Hello"を再代入
// 値を取り出す
std::string s = std::any_cast<std::string>(x);
assert(s == "Hello");
any
クラスは、古くからあったvoid*
をより便利にし、オブジェクトの寿命管理と実行時型情報の機能が付加された型であると言える。
このクラスと同様のことは、たとえばstd::shared_ptr<void>
でも行えるが、その場合はポインタの意味論で値を保持することになり、any
の場合は値の意味論で値を保持することになる。また、std::variant
クラスも似たようなことができるが、その違いは、variant
が代入されうる型の候補が静的に既知であることに対し、any
はその候補を実行時まで遅らせることができるということである。同じことを実現するためにどの設計を採用するかはプログラマに委ねられる。
使用例:
- イベントハンドラに渡されるパラメータの型として使用する
list<function<void(any)>>
のようなイベントのリストを保持しておき、たとえば0番目のイベントハンドラにはマウスクリック、1番目のイベントハンドラにはボタンクリックに使用すると想定する- マウスクリックにはイベントの引数としてクリックした位置情報 (xとy) が渡され、ボタンクリックにはイベントの引数としてボタンのIDが渡される、というような、イベントの種類ごとに引数の型が異なるという状況がでてくる
- イベントの種類ごとに異なるイベント変数 (
function<void(Point)>
とfunction<void(ButtonID)>
) を用意するかまとめて扱うかで設計選択があるが、そこでany
を使用するという選択肢がありうる
要件
- 代入する型はコピー構築可能であること
備考
- 実装は、小さなオブジェクトを保持するためには動的メモリ確保を回避するべきである。そのようなsmall-object optimizationは、代入される型
T
がstd::is_nothrow_move_constructible_v<T> == true
の場合にのみ適用されること
メンバ関数
構築・破棄
名前 | 説明 | 対応バージョン |
---|---|---|
(constructor) |
コンストラクタ | C++17 |
(destructor) |
デストラクタ | C++17 |
代入
名前 | 説明 | 対応バージョン |
---|---|---|
operator= |
代入演算子 | C++17 |
emplace |
要素型のコンストラクタ引数から直接構築する | C++17 |
swap |
他のany オブジェクトとデータを入れ替える |
C++17 |
reset |
有効値を保持していない状態にする | C++17 |
値の観測
名前 | 説明 | 対応バージョン |
---|---|---|
has_value |
有効な値を保持しているかを判定する | C++17 |
type |
保持している値の型情報を取得する | C++17 |
非メンバ関数
ヘルパ関数
名前 | 説明 | 対応バージョン |
---|---|---|
make_any |
any オブジェクトを構築する |
C++17 |
値の取り出し
名前 | 説明 | 対応バージョン |
---|---|---|
any_cast |
値を取り出す | C++17 |
値の入れ替え
名前 | 説明 | 対応バージョン |
---|---|---|
swap |
2つのany オブジェクトを入れ替える |
C++17 |
例
#include <iostream>
#include <any>
int main()
{
// int型の値を代入して取り出す
std::any x = 3;
int n = std::any_cast<int>(x);
std::cout << n << std::endl;
// 文字列を再代入して取り出す
x = "Hello";
const char* s = std::any_cast<const char*>(x);
std::cout << s << std::endl;
// 間違った型で取り出そうとすると例外が送出される
try {
std::any_cast<double>(x);
}
catch (std::bad_any_cast& e) {
std::cout << e.what() << std::endl;
}
}
xxxxxxxxxx
#include <iostream>
#include <any>
int main()
{
// int型の値を代入して取り出す
std::any x = 3;
int n = std::any_cast<int>(x);
std::cout << n << std::endl;
// 文字列を再代入して取り出す
x = "Hello";
const char* s = std::any_cast<const char*>(x);
std::cout << s << std::endl;
// 間違った型で取り出そうとすると例外が送出される
try {
std::any_cast<double>(x);
}
catch (std::bad_any_cast& e) {
std::cout << e.what() << std::endl;
}
}
出力例
3
Hello
bad any_cast
バージョン
言語
- C++17
処理系
- Clang: 4.0.1 ✅
- GCC: 7.3 ✅
- Visual C++: ??
参照
- P0220R1 Adopt Library Fundamentals V1 TS Components for C++17 (R1)
- P0032R0 Homogeneous interface for
variant
,any
andoptional
- P0032R1 Homogeneous interface for
variant
,any
andoptional
(Revision 1) - P0032R2 Homogeneous interface for
variant
,any
andoptional
(Revision 2) - P0032R3 Homogeneous interface for
variant
,any
andoptional
(Revision 3)