std::visit
提供: cppreference.com
<tbody>
</tbody>
| ヘッダ <variant> で定義
|
||
template <class Visitor, class... Variants> constexpr /*see below*/ visit(Visitor&& vis, Variants&&... vars); |
(1) | (C++17以上) |
template <class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...); |
(2) | (C++20以上) |
ビジター vis をバリアント vars に適用します。
実質的に
std::invoke(std::forward<Visitor>(vis), std::get<is>(std::forward<Variants>(vars))...)
を返します。 ただし is... は vars.index()... です。
1) 戻り値の型は
decltype によって行われたかのように返される式から推定されます。 すべての variant の選択肢型のすべての組み合わせについて、上記の呼び出しが同じ型および値カテゴリの有効な式でなければ、この呼び出しは ill-formed です。2) 戻り値の型は
R です。 R が void (または cv 修飾された void) の場合、 invoke 式の結果は破棄されます。引数
| vis | - | すべての variant からのすべての可能な選択肢を受理する Callable |
| vars | - | ビジターに渡す variant のリスト |
戻り値
1) ビジターの選択された呼び出しによって返された値。
2)
R が void (または cv 修飾された void) の場合は、なし。 そうでなければ、ビジターの選択された呼び出しによって返された値が R に暗黙に変換された値。例外
vars 内のいずれかの variant が valueless_by_exception の場合、 std::bad_variant_access を投げます。
計算量
variant の数が0または1のとき、 callable オブジェクトの呼び出しは定数時間で実装されます。 つまり sizeof...(Types) に依存しません。
variant の数が1より大きいとき、 callable オブジェクトの呼び出しに計算量の要件はありません。
例
Run this code
#include <iomanip>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
// visit するバリアント。
using var_t = std::variant<int, long, double, std::string>;
// ビジター #3 のためのヘルパー型。
template<class T> struct always_false : std::false_type {};
// ビジター #4 のためのヘルパー型。
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main() {
std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
for(auto& v: vec) {
// 1. void ビジター。 副作用 (ここでは入出力) のためだけに呼ばれます。
std::visit([](auto&& arg){std::cout << arg;}, v);
// 2. 値を返すビジター。 別のバリアントを返すイディオムをデモンストレーションします。
var_t w = std::visit([](auto&& arg) -> var_t {return arg + arg;}, v);
// 3. 型マッチングビジター。 それぞれの型に対して異なる処理をするラムダ。
std::cout << ". After doubling, variant holds ";
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
std::cout << "int with value " << arg << '\n';
else if constexpr (std::is_same_v<T, long>)
std::cout << "long with value " << arg << '\n';
else if constexpr (std::is_same_v<T, double>)
std::cout << "double with value " << arg << '\n';
else if constexpr (std::is_same_v<T, std::string>)
std::cout << "std::string with value " << std::quoted(arg) << '\n';
else
static_assert(always_false<T>::value, "non-exhaustive visitor!");
}, w);
}
for (auto& v: vec) {
// 4. 別の型マッチングビジター。 オーバーロードされた3つの operator() を持つクラス。
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}, v);
}
}
出力:
10. After doubling, variant holds int with value 20
15. After doubling, variant holds long with value 30
1.5. After doubling, variant holds double with value 3
hello. After doubling, variant holds std::string with value "hellohello"
10 15 1.500000 "hello"
関連項目
| 別の variant と交換します (パブリックメンバ関数) |