133 lines
3.1 KiB
C++
133 lines
3.1 KiB
C++
|
#include <iostream>
|
||
|
#include <vector>
|
||
|
#include <thread>
|
||
|
#include <string>
|
||
|
#include <sstream>
|
||
|
#include <utility>
|
||
|
#include <type_traits>
|
||
|
#include <boost/timer/timer.hpp>
|
||
|
#include "variant.hpp"
|
||
|
|
||
|
using namespace mapbox;
|
||
|
|
||
|
namespace test {
|
||
|
|
||
|
struct add;
|
||
|
struct sub;
|
||
|
template <typename OpTag> struct binary_op;
|
||
|
|
||
|
typedef util::variant<int ,
|
||
|
util::recursive_wrapper<binary_op<add>>,
|
||
|
util::recursive_wrapper<binary_op<sub>>
|
||
|
> expression;
|
||
|
|
||
|
template <typename Op>
|
||
|
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 : util::static_visitor<void>
|
||
|
{
|
||
|
template <typename T>
|
||
|
void operator() (T const& val) const
|
||
|
{
|
||
|
std::cerr << val << ":" << typeid(T).name() << std::endl;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
struct test : util::static_visitor<std::string>
|
||
|
{
|
||
|
template <typename T>
|
||
|
std::string operator() (T const& obj) const
|
||
|
{
|
||
|
return std::string("TYPE_ID=") + typeid(obj).name();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct calculator : public util::static_visitor<int>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
int operator()(int value) const
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
int operator()(binary_op<add> const& binary) const
|
||
|
{
|
||
|
return util::apply_visitor(calculator(), binary.left)
|
||
|
+ util::apply_visitor(calculator(), binary.right);
|
||
|
}
|
||
|
|
||
|
int operator()(binary_op<sub> const& binary) const
|
||
|
{
|
||
|
return util::apply_visitor(calculator(), binary.left)
|
||
|
- util::apply_visitor(calculator(), binary.right);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct to_string : public util::static_visitor<std::string>
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
std::string operator()(int value) const
|
||
|
{
|
||
|
return std::to_string(value);
|
||
|
}
|
||
|
|
||
|
std::string operator()(binary_op<add> const& binary) const
|
||
|
{
|
||
|
return util::apply_visitor(to_string(), binary.left) + std::string("+")
|
||
|
+ util::apply_visitor(to_string(), binary.right);
|
||
|
}
|
||
|
|
||
|
std::string operator()(binary_op<sub> 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] << " <num-iter>" << std::endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
|
||
|
const std::size_t NUM_ITER = static_cast<std::size_t>(std::stol(argv[1]));
|
||
|
|
||
|
test::expression result(
|
||
|
test::binary_op<test::sub>(
|
||
|
test::binary_op<test::add>(2, 3), 4));
|
||
|
|
||
|
std::cerr << "TYPE OF RESULT-> " << util::apply_visitor(test::test(), result) << std::endl;
|
||
|
|
||
|
{
|
||
|
boost::timer::auto_cpu_timer t;
|
||
|
int total = 0;
|
||
|
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;
|
||
|
}
|