我有一个模拟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_;
};
有什么想法吗?
答案 0 :(得分: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_;
}