#include #include #include #include #include #include #include "auto_cpu_timer.hpp" #include using namespace mapbox; namespace test { struct add; struct sub; template struct binary_op; typedef util::variant>, std::unique_ptr>> expression; template struct binary_op { expression left; // variant instantiated here... expression right; binary_op(expression&& lhs, expression&& rhs) : left(std::move(lhs)), right(std::move(rhs)) { } }; struct print { template void operator()(T const& val) const { std::cerr << val << ":" << typeid(T).name() << std::endl; } }; struct test { template std::string operator()(T const& obj) const { return std::string("TYPE_ID=") + typeid(obj).name(); } }; struct calculator { public: int operator()(int value) const { return value; } int operator()(std::unique_ptr> const& binary) const { return util::apply_visitor(calculator(), binary->left) + util::apply_visitor(calculator(), binary->right); } int operator()(std::unique_ptr> const& binary) const { return util::apply_visitor(calculator(), binary->left) - util::apply_visitor(calculator(), binary->right); } }; struct to_string { public: std::string operator()(int value) const { return std::to_string(value); } std::string operator()(std::unique_ptr> const& binary) const { return util::apply_visitor(to_string(), binary->left) + std::string("+") + util::apply_visitor(to_string(), binary->right); } std::string operator()(std::unique_ptr> const& binary) const { return util::apply_visitor(to_string(), binary->left) + std::string("-") + util::apply_visitor(to_string(), binary->right); } }; } // namespace test int main(int argc, char** argv) { if (argc != 2) { std::cerr << "Usage" << argv[0] << " " << std::endl; return EXIT_FAILURE; } const std::size_t NUM_ITER = static_cast(std::stol(argv[1])); test::expression sum(std::unique_ptr>(new test::binary_op(2, 3))); test::expression result(std::unique_ptr>(new test::binary_op(std::move(sum), 4))); std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl; int total = 0; { auto_cpu_timer t; for (std::size_t i = 0; i < NUM_ITER; ++i) { total += util::apply_visitor(test::calculator(), result); } } std::cerr << "total=" << total << std::endl; std::cerr << util::apply_visitor(test::to_string(), result) << "=" << util::apply_visitor(test::calculator(), result) << std::endl; return EXIT_SUCCESS; }