Created
December 13, 2012 09:20
-
-
Save rhysd/4275201 to your computer and use it in GitHub Desktop.
representation for expression tree using boost::variant
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <boost/variant/variant.hpp> | |
#include <boost/variant/recursive_wrapper.hpp> | |
#include <boost/variant/static_visitor.hpp> | |
#include <boost/variant/apply_visitor.hpp> | |
struct add_tag{ static char const* symbol(){ static char const* s = "+"; return s; } }; | |
struct sub_tag{ static char const* symbol(){ static char const* s = "-"; return s; } }; | |
struct mul_tag{ static char const* symbol(){ static char const* s = "*"; return s; } }; | |
struct div_tag{ static char const* symbol(){ static char const* s = "/"; return s; } }; | |
template<class Op> | |
struct binary_operator; | |
typedef boost::variant< double | |
, boost::recursive_wrapper<binary_operator<add_tag> > | |
, boost::recursive_wrapper<binary_operator<sub_tag> > | |
, boost::recursive_wrapper<binary_operator<mul_tag> > | |
, boost::recursive_wrapper<binary_operator<div_tag> > | |
> expression; | |
template<class Op> | |
struct binary_operator { | |
expression left; | |
expression right; | |
binary_operator(expression const& lhs, expression const& rhs) | |
: left(lhs), right(rhs){} | |
}; | |
struct calculator : public boost::static_visitor<double>{ | |
double operator()(double const constant) const | |
{ | |
return constant; | |
} | |
double operator()(binary_operator<add_tag> const& op) const | |
{ | |
return boost::apply_visitor( calculator(), op.left ) | |
+ boost::apply_visitor( calculator(), op.right ); | |
} | |
double operator()(binary_operator<sub_tag> const& op) const | |
{ | |
return boost::apply_visitor( calculator(), op.left ) | |
- boost::apply_visitor( calculator(), op.right ); | |
} | |
double operator()(binary_operator<mul_tag> const& op) const | |
{ | |
return boost::apply_visitor( calculator(), op.left ) | |
* boost::apply_visitor( calculator(), op.right ); | |
} | |
double operator()(binary_operator<div_tag> const& op) const | |
{ | |
return boost::apply_visitor( calculator(), op.left ) | |
/ boost::apply_visitor( calculator(), op.right ); | |
} | |
}; | |
inline double calc( expression const& expr ) | |
{ | |
return boost::apply_visitor(calculator(), expr); | |
} | |
struct stringizer : public boost::static_visitor<std::string>{ | |
std::string operator()(double const constant) const | |
{ | |
return std::to_string(constant); | |
} | |
template<class Op> | |
std::string operator()(binary_operator<Op> const& op) const | |
{ | |
return '(' + boost::apply_visitor(stringizer(), op.left) | |
+ Op::symbol() | |
+ boost::apply_visitor(stringizer(), op.right) + ')'; | |
} | |
}; | |
inline std::string stringize(expression const& expr) | |
{ | |
return boost::apply_visitor(stringizer(), expr); | |
} | |
int main() | |
{ | |
expression result(binary_operator<div_tag>( | |
binary_operator<add_tag>( | |
binary_operator<sub_tag>(7, 3) | |
, binary_operator<mul_tag>(2, 3) | |
) | |
, 3) | |
); | |
std::cout << stringize(result) << " = " << calc(result) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment