1216 typeErasure 상속없이 다형성

// TYPE ERASURE in C++
//  이건 cpp-bind-any-methods에서도 쓰였던 기법.

// draw라는 메서드가 있다는 가정.
struct DrawableConcept {
    virtual ~DrawableConcept() = default;
    virtual void draw() const = 0;
};

// draw메서드가 있는 형식 T에 대해 묶음
template<typename T>
struct DrawableModel : DrawableConcept {
    T object;

    DrawableModel(T obj) : object(std::move(obj)) {}

    void draw() const override {
        object.draw();
    }
};

// 여기서 템플릿은 "클래스" 단에 있지 않음.            ->  Drawable 단독으로 사용가능.
//  대신 생성자에서 T를 결정하고 T*를 저장해둠.
class Drawable {
public:
    template<typename T>
    Drawable(T obj)
        : self(std::make_unique<DrawableModel<T>>(std::move(obj))) {}

    void draw() const {
        self->draw();
    }

private:
    std::unique_ptr<DrawableConcept> self;
};

// Circlr과 Square은 아무 관련도 없는 클래스임.
//  그러나 void draw라는 공통점이 있으므로.
struct Circle {
    void draw() const { std::cout << "Circle\n"; }
};

struct Square {
    void draw() const { std::cout << "Square\n"; }
};

int main() {
    std::vector<Drawable> shapes;
    shapes.emplace_back(Circle{});
    shapes.emplace_back(Square{});

    for (const auto& s : shapes)
        s.draw();
}