3

ツリーを構築するために、Boost のバリアント型を広範囲に使用しています。より正確には、Boost の Qi を使用して文法からツリーを解析し、ツリーをトラバースして各ノードに整数で注釈を付けます。少なくともそれが私がやりたいことです。

static_visitor はポインターとしてノードを訪問しないため、値フィールドを変更できない可能性があることに気付きました。そのため、バリアント自体ではなく、バリアント型のポインターで 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 へのポインターにすることです。

4

1 に答える 1

2

参照によって取得されたオブジェクトを大幅に変更できます。

    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";
}
于 2014-05-12T07:35:10.713 に答える