名前空間
変種
操作

std::visit

提供: cppreference.com
< cpp‎ | utility‎ | variant
 
 
 
 
ヘッダ <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 です。 Rvoid (または cv 修飾された void) の場合、 invoke 式の結果は破棄されます。

目次

[編集] 引数

vis - すべての variant からのすべての可能な選択肢を受理する Callable
vars - ビジターに渡す variant のリスト

[編集] 戻り値

1) ビジターの選択された呼び出しによって返された値。
2) Rvoid (または cv 修飾された void) の場合は、なし。 そうでなければ、ビジターの選択された呼び出しによって返された値が R に暗黙に変換された値。

[編集] 例外

vars 内のいずれかの variant が valueless_by_exception の場合、 std::bad_variant_access を投げます。

[編集] 計算量

variant の数が0または1のとき、 callable オブジェクトの呼び出しは定数時間で実装されます。 つまり sizeof...(Types) に依存しません。

variant の数が1より大きいとき、 callable オブジェクトの呼び出しに計算量の要件はありません。

[編集]

#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 と交換します
(パブリックメンバ関数) [edit]