从访问者到另一个访问者转发boost :: variant

时间:2016-04-17 21:29:02

标签: c++ boost boost-variant

我想从其他访问者的内部呼叫访问者。请考虑以下代码:

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

1 个答案:

答案 0 :(得分:3)

如果您想要使用该变体,只需直接调用它(无需使用apply_visitor)。

如果您想另外,只需使用bind或类似内容:

<强> Live On 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)

替代无绑定

如果你喜欢DIY,你可以轻松地模仿“绑定”:

<强> Live On 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-aware,然后你可以隐藏“双重绑定”:

<强> Live On 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)