⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test_multimethods.cpp

📁 Modern C++ Design 一书中实现的程序库
💻 CPP
字号:
#include <iostream>
#include <typeinfo>
#include <memory>
#include <cassert>
#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<class TestedHachingDispatcher, class TestedHachingExecutor>
void Test_HachingDispatcher(TestedHachingExecutor Exec)
{
    using ::std::auto_ptr;

    auto_ptr<Shape>   shape1(new Rectangle);
    auto_ptr<Shape>   shape2(new Ellipse);
    auto_ptr<Shape>   shape3(new Poly);
    auto_ptr<Shape>   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<Shape>   ShapeBasicDispatcher;
typedef ::Loki::FnDispatcher<Shape>      ShapeFnDispatcher;
typedef ::Loki::FunctorDispatcher<Shape> ShapeFunctorDispatcher;
            
namespace // anonymous
{
    template<class Shape1, class Shape2>
    void HatchShapesDo(Shape1 &, Shape2 &)
    {
        cout << "HatchShapes: " 
             << typeid(Shape1).name() << ", "
             << typeid(Shape2).name() << '\n';
    }

    template<class Shape1, class Shape2>
    void HatchShapes(Shape &lhs, Shape &rhs)
    {
        assert(dynamic_cast<Shape1*>(&lhs) != 0);
        assert(dynamic_cast<Shape2*>(&rhs) != 0);

        HatchShapesDo(static_cast<Shape1&>(lhs),
                      static_cast<Shape2&>(rhs));
    }

    template<class Shape1, class Shape2>
    struct HatchShapesFunctor
    {
        void operator()(Shape1 &lhs, Shape2 &rhs)
        {
            HatchShapesDo(lhs, rhs);
        }
    };

} // anonymous namespace

template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeBasicDispatcher &x)
{
    x.Add<Shape1, Shape2>(HatchShapes<Shape1, Shape2>);
}

template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeFnDispatcher &x)
{
    x.Add<Shape1, Shape2>(HatchShapes<Shape1, Shape2>);
}

template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeFunctorDispatcher &x)
{
    x.Add<Shape1, Shape2>(HatchShapesFunctor<Shape1, Shape2>());
}

template<class Dispacher>
void Test_LogDispacher()
{
    Dispacher    testedBasicDispatcher;

    ShapeDispatcherAdd<Rectangle, Poly>(testedBasicDispatcher);
    ShapeDispatcherAdd<Poly, Rectangle>(testedBasicDispatcher);
    ShapeDispatcherAdd<Rectangle, Ellipse>(testedBasicDispatcher);
    ShapeDispatcherAdd<Ellipse, Poly>(testedBasicDispatcher);
    ShapeDispatcherAdd<Poly, Poly>(testedBasicDispatcher);


    using ::std::auto_ptr;

    auto_ptr<Shape>   shape1(new Rectangle);
    auto_ptr<Shape>   shape2(new Ellipse);
    auto_ptr<Shape>   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<SymHachingDispatcher>(SymExec);

    HachingExecutor     Exec;
    Test_HachingDispatcher<HachingDispatcher>(Exec);

    Test_LogDispacher<ShapeBasicDispatcher>();
    Test_LogDispacher<ShapeFnDispatcher>();
    Test_LogDispacher<ShapeFunctorDispatcher>();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -