#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <ctime>
#include <iostream>
#include <memory>
namespace use_var
{
struct NoIntersection {
// empty
};
struct Point {
int x, y;
Point(int x,int y) : x(x),y(y) {}
};
struct Circle {
Point c;
int r;
Circle(Point const & c, int r) : c(c), r(r) {}
};
typedef boost::variant<NoIntersection, Point, Circle> IntersectionResult;
IntersectionResult intersection_test(int i) {
if(i % 2 == 0){
return NoIntersection();
}
if(i % 3 == 0){
return Point(i, i * 2);
}
return Circle(Point(i, i * 2), i * 3);
}
struct process_result_visitor : public boost::static_visitor<> {
int results[3];
process_result_visitor() { results[0] = results[1] = results[2] = 0; }
void operator()(NoIntersection) {
++results[0];
}
void operator()(Point const &) {
++results[1];
}
void operator()(Circle const &) {
++results[2];
}
};
double do_test(int N) // returns time in microseconds
{
std::clock_t const start = std::clock();
process_result_visitor processor;
for(int i = 0; i < N; ++i)
{
IntersectionResult result = intersection_test(i);
boost::apply_visitor(processor, result);
}
std::clock_t const end = std::clock();
return (double(end - start) / N) / CLOCKS_PER_SEC * 1e6;
}
}
namespace use_union
{
struct NoIntersection {
// empty
};
struct Point {
int x, y;
};
struct Circle {
Point c;
int r;
};
struct IntersectionResult
{
enum Type { NoInter, PointInter, CircleInter };
Type type;
union
{
Point p;
Circle c;
} data;
};
IntersectionResult intersection_test(int i) {
IntersectionResult result;
if(i % 2 == 0){
result.type = IntersectionResult::NoInter;
}
else if(i % 3 == 0){
result.type = IntersectionResult::PointInter;
Point p = { i, i * 2 };
result.data.p = p;
}
else {
result.type = IntersectionResult::PointInter;
Circle c = { { i, i * 2 }, i * 3 };
result.data.c = c;
}
return result;
}
struct result_processor {
int results[3];
result_processor() { results[0] = results[1] = results[2] = 0; }
void operator()(IntersectionResult const & result) {
++results[result.type];
}
};
double do_test(int N) // returns time in microseconds
{
std::clock_t const start = std::clock();
result_processor processor;
for(int i = 0; i < N; ++i)
{
IntersectionResult result = intersection_test(i);
processor(result);
}
std::clock_t const end = std::clock();
return (double(end - start) / N) / CLOCKS_PER_SEC * 1e6;
}
}
namespace use_hierarchy
{
struct IntersectionResult
{
virtual ~IntersectionResult() { }
};
struct NoIntersection : public IntersectionResult {
// empty
};
struct Point : public IntersectionResult {
int x, y;
Point(int x,int y) : x(x),y(y) {}
};
struct Circle : public IntersectionResult {
Point c;
int r;
Circle(Point const & c, int r) : c(c), r(r) {}
};
std::auto_ptr<IntersectionResult> intersection_test(int i) {
if(i % 2 == 0){
return std::auto_ptr<IntersectionResult>(new NoIntersection);
}
if(i % 3 == 0){
return std::auto_ptr<IntersectionResult>(new Point(i, i * 2));
}
return std::auto_ptr<IntersectionResult>(new Circle(Point(i, i * 2), i * 3));
}
struct result_processor {
int results[3];
result_processor() { results[0] = results[1] = results[2] = 0; }
void operator()(IntersectionResult const & result) {
if(dynamic_cast<NoIntersection const *>(&result))
++results[0];
else if(dynamic_cast<Point const *>(&result))
++results[1];
else
++results[2];
}
};
double do_test(int N) // returns time in microseconds
{
std::clock_t const start = std::clock();
result_processor processor;
for(int i = 0; i < N; ++i)
{
std::auto_ptr<IntersectionResult> result(intersection_test(i));
processor(*result);
}
std::clock_t const end = std::clock();
return (double(end - start) / N) / CLOCKS_PER_SEC * 1e6;
}
}
namespace use_any
{
using use_var::NoIntersection;
using use_var::Point;
using use_var::Circle;
typedef boost::any IntersectionResult;
using use_var::intersection_test;
struct result_processor {
int results[3];
result_processor() { results[0] = results[1] = results[2] = 0; }
void operator()(IntersectionResult const & result) {
if(result.type() == typeid(NoIntersection))
++results[0];
else if(result.type() == typeid(Point))
++results[1];
else
++results[2];
}
};
double do_test(int N) // returns time in microseconds
{
std::clock_t const start = std::clock();
result_processor processor;
for(int i = 0; i < N; ++i)
{
IntersectionResult result(intersection_test(i));
processor(result);
}
std::clock_t const end = std::clock();
return (double(end - start) / N) / CLOCKS_PER_SEC * 1e6;
}
}
int main()
{
int const N = 1000000;
double use_var_time = use_var::do_test(N);
std::cout << "test with boost::variant took " << use_var_time << " microseconds\n";
double use_union_time = use_var::do_test(N);
std::cout << "test with union took " << use_union_time << " microseconds\n";
double use_hierarchy_time = use_hierarchy::do_test(N);
std::cout << "test with hierarchy took " << use_hierarchy_time << " microseconds\n";
double use_any_time = use_any::do_test(N);
std::cout << "test with boost::any took " << use_any_time << " microseconds\n";
return 0;
}