向前推进::从一个访问者到另一个访问者的变体

Forward boost::variant from a visitor to another

本文关键字:访问者 一个 另一个      更新时间:2023-10-16

我想从另一个访问者内部调用boost变体的访问者。考虑以下代码:

struct visitor1 : boost::static_visitor<>
{
    void operator()(const int& i) const { std::cout << "visitor1:" << i; }
    void operator()(const std::string & str) const { std::cout << "visitor1, string: " << str}
};
struct visitor2 : boost::static_visitor<>
{
    void operator()(const int& i) const
    {
        // apply visitor1 here
        boost::apply_visitor(visitor1(), /* is there a context reference to the variant here? */)
        std::cout << "visitor 2 applied visitor 1";
    }
    void operator()(const std::string & str) const { //... }
};
int main()
{
  boost::variant< int, std::string> v = 5;
  boost::apply_visitor(visitor2 (), v );
}

应输出:

visitor1: 5
Visitor 2 applied visitor 1

如果您想接受变体,只需直接调用它(witout apply_viewer)。

如果你想服用只需使用bind或类似药物:

在Coliru上直播

#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <iostream>
struct visitor1 : boost::static_visitor<>
{
    void operator()(const int& i) const            { std::cout << "visitor1:"          << i   << "n"; }
    void operator()(const std::string & str) const { std::cout << "visitor1, string: " << str << "n"; }
};
struct visitor2 : boost::static_visitor<>
{
    template <typename  Variant>
    void operator()(const int& i, Variant const& v) const
    {
        boost::apply_visitor(visitor1(), v);
        std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")n";
    }
    template <typename  Variant>
    void operator()(const std::string & str, Variant const& v) const { 
        boost::apply_visitor(visitor1(), v);
        std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")n";
    }
};
int main()
{
    using V = boost::variant< int, std::string>;
    for (V v : { V{5}, V{"something"} })
        boost::apply_visitor(boost::bind(visitor2(), _1, boost::ref(v)), v);
}

打印

visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)

无约束的备选方案

如果你喜欢自己动手,你可以很容易地模仿"绑定":

在Coliru上直播

template <typename V>
struct visitor2 {
    typedef void result_type;
    V const* _ref;
    void operator()(const int& i) const {
        boost::apply_visitor(visitor1(), *_ref);
        std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")n";
    }
    void operator()(const std::string & str) const { 
        boost::apply_visitor(visitor1(), *_ref);
        std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")n";
    }
};
int main()
{
    using V = boost::variant< int, std::string>;
    for (V v : { V{5}, V{"something"} })
        boost::apply_visitor(visitor2<V>{&v}, v);
}

打印

visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)

风格笔记:

我喜欢让函数对象Variant知道,然后你可以隐藏"双重绑定":

在Coliru上直播

struct visitor2 {
    typedef void result_type;
    template <typename... Ts>
        void operator()(boost::variant<Ts...> const& v) const {
            return boost::apply_visitor(boost::bind(*this, _1, boost::cref(v)), v);
        }
    template <typename Variant>
    void operator()(const int& i, Variant const& v) const {
        boost::apply_visitor(visitor1(), v);
        std::cout << "visitor 2 applied visitor 1" << " (int " << i << ")n";
    }
    template <typename Variant>
    void operator()(const std::string & str, Variant const& v) const { 
        boost::apply_visitor(visitor1(), v);
        std::cout << "visitor 2 applied visitor 1" << " (string " << str << ")n";
    }
};
int main()
{
    using V = boost::variant< int, std::string>;
    for (V v : { V{5}, V{"something"} })
        visitor2{}(v);
}

打印

visitor1:5
visitor 2 applied visitor 1 (int 5)
visitor1, string: something
visitor 2 applied visitor 1 (string something)