让static_visitor在遍历Boost递归变量时修改它



我广泛使用Boost的变体类型来构建树。更准确地说,我使用Boost的Qi从语法解析树,然后遍历树,用整数注释每个节点—至少这是我想要做的。

我刚刚意识到,因为static_visitor不以指针的形式访问节点,所以我不可能修改value字段。因此,我试图让static_visitor在变量类型的指针上工作,而不是变体本身。

一个简化的例子:

typedef struct s_node node;

typedef boost::variant<
        int,
        boost::recursive_wrapper<node>,
        > tree;
struct s_node
{
  tree left, right;
  double value;
  explicit s_node(const expr& l, const expr& r) : oper1(l), oper2(r) { value = -1.0; }
};
struct Traversal : boost::static_visitor<void>
{
  void operator()(int *i) const { return; }
  void operator()(node *b) {
    b->value = 10.0;
  }
};

但是它不起作用。当我尝试做:

Traversal t;
boost::apply_visitor(t, &tree);

我得到一个错误:

test.cpp:253:21: error: no matching function for call to 'apply_visitor'
...

如何让static_visitor做我想做的?有更好的方法吗?目前,我考虑的唯一想法是使节点结构内的字段成为指向int型的指针,而不是int型。

你可以很容易地修改引用对象:

    void operator()(int) const { }
    void operator()(s_node& b) const {
        b.value = 10.0;
    }

查看Live On Coliru,输出:

Before: s_node {5, s_node {7, 42 /*value: -1*/} /*value: -1*/}
After:  s_node {5, s_node {7, 42 /*value: -1*/} /*value: 10*/}

完整样例:

#include <boost/variant.hpp>
#include <iostream>
struct s_node;
typedef boost::variant<
        int,
        boost::recursive_wrapper<s_node>
    > expr;
struct s_node
{
    expr oper1, oper2;
    double value;
    explicit s_node(const expr& l, const expr& r)
        : oper1(l), oper2(r), value(-1) { }
    friend std::ostream& operator<<(std::ostream& os, s_node const& n) {
        return os << "s_node {" << n.oper1 << ", " << n.oper2 << " /*value: " << n.value << "*/}";
    }
};
struct Traversal : boost::static_visitor<void>
{
    void operator()(int) const { }
    void operator()(s_node& b) const {
        b.value = 10.0;
    }
};
int main()
{
    expr x = s_node(5, s_node(7, 42));
    std::cout << "Before: " << x << "n";
    boost::apply_visitor(Traversal(), x);
    std::cout << "After:  " << x << "n";
}

相关内容

  • 没有找到相关文章

最新更新