我已经用我自己的微小努力替换了开放类型切换(我无法让它工作;还有 boost-variant 它都是内置的):
namespace visitor_galore // this is my make-shift replacement for typeswitch (I couldn't find it/make it work)
{
template<typename T, class...Fs> struct visitor_t;
template<typename T, class F1, class...Fs>
struct visitor_t<T, F1, Fs...> : F1, visitor_t<T, Fs...>::type {
typedef visitor_t type;
visitor_t(F1 head, Fs...tail) : F1(head), visitor_t<T, Fs...>::type(tail...) {}
using F1::operator();
using visitor_t<T, Fs...>::type::operator();
};
template<typename T, class F> struct visitor_t<T, F> : F, boost::static_visitor<T> {
typedef visitor_t type;
visitor_t(F f) : F(f) {}
using F::operator();
};
template<typename T=void, class...Fs>
typename visitor_t<T, Fs...>::type make_visitor(Fs...x) { return {x...}; }
}
using visitor_galore::make_visitor;
要了解如何使用它,请查看例如ast_pp.cpp
:
void pretty_print(expression_incdec const& exp)
{
boost::apply_visitor(
make_visitor(
[&exp](inc_dec_op_preinc const& op) { std::cout << "++"; pretty_print(exp.variable); },
[&exp](inc_dec_op_predec const& op) { std::cout << "--"; pretty_print(exp.variable); },
[&exp](inc_dec_op_postinc const& op) { pretty_print(exp.variable); std::cout << "++"; },
[&exp](inc_dec_op_postdec const& op) { pretty_print(exp.variable); std::cout << "--"; }
)
, exp.operatur);
}
奖励如果您不太关心列出分支中的所有类型,例如因为它们都默认调用相同的自由函数(或重载),您可以使用多态访问者:
static const struct pretty_print_visitor_ : boost::static_visitor<>
{
template<typename T>
void operator ()(T const& v) const { pretty_print(v); }
} pretty_print_visitor;
例如,现在您可以将 24 个分支替换为expression&
:
boost::apply_visitor(
make_visitor(
[](expression_binop const& exp) { pretty_print(exp); },
[](expression_unop const& exp) { pretty_print(exp); },
[](expression_integer_constant const& exp) { pretty_print(exp); },
[](expression_character_constant const& exp) { pretty_print(exp); },
[](expression_string_constant const& exp) { pretty_print(exp); },
[](expression_boolean_constant const& exp) { pretty_print(exp); },
[](expression_null const& exp) { pretty_print(exp); },
[](expression_this const& exp) { pretty_print(exp); },
[](expression_static_invoke const& exp) { pretty_print(exp); },
[](expression_non_static_invoke const& exp) { pretty_print(exp); },
[](expression_simple_invoke const& exp) { pretty_print(exp); },
[](expression_ambiguous_invoke const& exp) { pretty_print(exp); },
[](expression_new const& exp) { pretty_print(exp); },
[](expression_new_array const& exp) { pretty_print(exp); },
[](expression_lvalue const& exp) { pretty_print(exp); },
[](expression_assignment const& exp) { pretty_print(exp); },
[](expression_incdec const& exp) { pretty_print(exp); },
[](expression_cast const& exp) { pretty_print(exp); },
[](expression_ambiguous_cast const& exp) { pretty_print(exp); },
[](expression_instance_of const& exp) { pretty_print(exp); },
[](expression_parentheses const& exp) { pretty_print(exp); },
[](lvalue_non_static_field const& exp) { pretty_print(exp); },
[](lvalue_array const& exp) { pretty_print(exp); },
[](lvalue_ambiguous_name const& exp) { pretty_print(exp); }
)
, exp);
通过一个简单的
boost::apply_visitor(pretty_print_visitor, exp);