4

S式をモデル化する再帰バリアントがあります。

   struct sexpr {
      typedef boost::variant<
         nil,
         int,
         double,
         symbol,
         string,
         boost::recursive_wrapper<list<sexpr> >
      > node_type;

      node_type node;
   };

空のリストを常にnil(ではなくlist<sexpr>)で表すようにします。ただし、push_back()ビジターの実装に固執しています。基になるタイプがの場合、そのタイプをに変更して、指定された値をプッシュバックしnilたいと思います。list<sexpr>

   struct push_back_visitor: public boost::static_visitor<void>
   {
      push_back_visitor(const sexpr &arg): arg_(arg) {}

      template <typename T>
      void operator()(const T &value) const {
         throw bad_visit();
      }

      void operator()(nil &val) const {
         // how to change the underlying type to list<sexpr> here?
         // lst.push_back(arg_);
      }

      void operator()(list<sexpr> &lst) const {
         lst.push_back(arg_);
      }

      sexpr arg_;
   };

何か案は?

4

1 に答える 1

3

boost::variant訪問者内からバリアントにアクセスするメカニズムを提供しません。ただし、バリアント自体への参照を運ぶために訪問者を変更またはラップすることを妨げるものは何もありません。そのバリアントを訪問する訪問者内からバリアントのタイプを変更することは、ドキュメントには記載されていませんが、安全であるように見えます(バリアント訪問者の適用関数は、訪問者が呼び出されるとすぐに戻る必要があるため)。

template<typename Variant, typename Visitor>
struct carry_variant_visitor
  : public boost::static_visitor<typename Visitor::result_type>
{
    carry_variant_visitor(Variant &variant, Visitor visitor):
        variant_(variant), visitor_(visitor) { }
    template<typename T> 
    typename Visitor::result_type operator()(T &t) const {
        return visitor_(variant_, t);
    }
    Variant &variant_;
    Visitor visitor_;
}
于 2012-07-30T09:19:14.710 に答える