www.pudn.com > Loki.rar > Test_MultiMethods.cpp


#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(); 
}