4

我有一个模拟 S 表达式的递归变体:

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

      node_type node;
   };

我希望空列表始终由nil(not 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 回答