読者です 読者をやめる 読者になる 読者になる

Boost.Variant に型指定でアクセスしたい

boost::variant の要素にアクセスする場合,which() メンバ関数で boost::variant が保持している値の型を見てからアクセスするか static_visitor でアクセスするかの二択が普通だと思うけれど,「which() でアクセスするのはマジックナンバー増えるから嫌」「ちょっとアクセスするだけで static_visitor を定義するのは大仰すぎる」ということで,型でアクセスできる関数がほしいなとなった.

ので,作ったみた. 戻り値型は boost::optional で,boost::variant が目的の型の値を保持していなければ boost::none を返す.

#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/optional.hpp>

template<class T>
struct static_getter : public boost::static_visitor<boost::optional<T>>
{
    typedef boost::optional<T> return_type;

    return_type operator()(T const& val) const
    {
        return val;
    }

    template<class U>
    return_type operator()(U const&) const
    {
        return boost::none;
    }
};

template<class T, class Variant>
inline boost::optional<T> get(Variant const& v)
{
    return boost::apply_visitor(static_getter<T>{}, v);
}

#include <boost/variant/variant.hpp>
#include <iostream>

template<class O>
void print_optional(O const& o)
{
    if (o) {
        std::cout << *o << std::endl;
    } else {
        std::cout << "none\n";
    }
}

int main()
{
    boost::variant<int, double> v = 42;
    print_optional(get<int>(v));        //  42
    print_optional(get<double>(v));     //  none

    return 0;
}

なんか調べてみたら type() というメンバ関数があって,std::type_info を返すらしいので,それ使うという手もありそう.