#include #include #include #include #include "MultiMethods.h" using ::std::cout; struct Shape { virtual ~Shape() = 0; }; Shape::~Shape() {} class Rectangle : public Shape {}; class Poly : public Shape {}; class Ellipse : public Shape {}; class Cycloid : public Shape {}; class SymHachingExecutor { public: typedef void ResultType; ResultType Fire(Rectangle&, Rectangle&) { cout << "Fire(Rectangle&, Rectangle&)" << '\n'; } ResultType Fire(Rectangle&, Poly&) { cout << "Fire(Rectangle&, Poly&)" << '\n'; } ResultType Fire(Rectangle&, Ellipse&) { cout << "Fire(Rectangle&, Ellipse&)" << '\n'; } ResultType Fire(Poly&, Poly&) { cout << "Fire(Poly&, Poly&)" << '\n'; } ResultType Fire(Poly&, Ellipse&) { cout << "Fire(Poly&, Ellipse&)" << '\n'; } ResultType Fire(Ellipse&, Ellipse&) { cout << "Fire(Ellipse&, Ellipse&)" << '\n'; } void OnError(Shape& x, Shape& y) { cout << "OnError: " << typeid(x).name() << ", " << typeid(y).name() << '\n'; } }; typedef ::Loki::StaticDispatcher < SymHachingExecutor, Shape, TYPELIST_3(Rectangle, Poly, Ellipse) > SymHachingDispatcher; class HachingExecutor : SymHachingExecutor { public: typedef SymHachingExecutor::ResultType ResultType; using SymHachingExecutor::Fire; ResultType Fire(Poly&, Rectangle&) { cout << "Fire(Poly&, Rectangle&)" << '\n'; } ResultType Fire(Ellipse&, Rectangle&) { cout << "Fire(Ellipse&, Rectangle&)" << '\n'; } ResultType Fire(Ellipse&, Poly&) { cout << "Fire(Ellipse&, Poly&)" << '\n'; } using SymHachingExecutor::OnError; }; typedef ::Loki::StaticDispatcher < HachingExecutor, Shape, TYPELIST_3(Rectangle, Poly, Ellipse), false > HachingDispatcher; template void Test_HachingDispatcher(TestedHachingExecutor Exec) { using ::std::auto_ptr; auto_ptr shape1(new Rectangle); auto_ptr shape2(new Ellipse); auto_ptr shape3(new Poly); auto_ptr shape4(new Cycloid); static const std::size_t number_of_shapes = 4; Shape * const shapes[number_of_shapes] = { shape1.get(), shape2.get(), shape3.get(), shape4.get(), }; for (std::size_t i = 0 ; i < number_of_shapes ; ++i) for (std::size_t j = 0 ; j < number_of_shapes ; ++j) { TestedHachingDispatcher::Go(*shapes[i], *shapes[j], Exec); } } typedef ::Loki::BasicDispatcher ShapeBasicDispatcher; typedef ::Loki::FnDispatcher ShapeFnDispatcher; typedef ::Loki::FunctorDispatcher ShapeFunctorDispatcher; namespace // anonymous { template void HatchShapesDo(Shape1 &, Shape2 &) { cout << "HatchShapes: " << typeid(Shape1).name() << ", " << typeid(Shape2).name() << '\n'; } template void HatchShapes(Shape &lhs, Shape &rhs) { assert(dynamic_cast(&lhs) != 0); assert(dynamic_cast(&rhs) != 0); HatchShapesDo(static_cast(lhs), static_cast(rhs)); } template struct HatchShapesFunctor { void operator()(Shape1 &lhs, Shape2 &rhs) { HatchShapesDo(lhs, rhs); } }; } // anonymous namespace template void ShapeDispatcherAdd(ShapeBasicDispatcher &x) { x.Add(HatchShapes); } template void ShapeDispatcherAdd(ShapeFnDispatcher &x) { x.Add(HatchShapes); } template void ShapeDispatcherAdd(ShapeFunctorDispatcher &x) { x.Add(HatchShapesFunctor()); } template void Test_LogDispacher() { Dispacher testedBasicDispatcher; ShapeDispatcherAdd(testedBasicDispatcher); ShapeDispatcherAdd(testedBasicDispatcher); ShapeDispatcherAdd(testedBasicDispatcher); ShapeDispatcherAdd(testedBasicDispatcher); ShapeDispatcherAdd(testedBasicDispatcher); using ::std::auto_ptr; auto_ptr shape1(new Rectangle); auto_ptr shape2(new Ellipse); auto_ptr shape3(new Poly); static const std::size_t number_of_shapes = 3; Shape * const shapes[number_of_shapes] = { shape1.get(), shape2.get(), shape3.get(), }; for (std::size_t i = 0 ; i < number_of_shapes ; ++i) for (std::size_t j = 0 ; j < number_of_shapes ; ++j) { try { testedBasicDispatcher.Go(*shapes[i], *shapes[j]); } catch(::std::runtime_error &exp) { cout << exp.what() << ": " << typeid(*shapes[i]).name() << ", " << typeid(*shapes[j]).name() << '\n'; } } } int main() { SymHachingExecutor SymExec; Test_HachingDispatcher(SymExec); HachingExecutor Exec; Test_HachingDispatcher(Exec); Test_LogDispacher(); Test_LogDispacher(); Test_LogDispacher(); }