// ----- vtableを使用したType Erasure -----
// επιστημη + 高橋 晶 著
// 『完結で再利用しやすいコードのためのC++活用術 C++テンプレートテクニック』より
#include <iostream>
class drawable {
struct vtable {
void (*draw)(void*);
};
/*
それぞれの型ごとのvtbl_,draw()を保持
*/
template <class T>
struct vtable_initializer {
static vtable vtbl_;
static void draw(void* this_)
{
static_cast<T*>(this_)->draw();
}
};
void* this_;
vtable* vptr_;
public:
template <class T>
drawable(T& other)
: this_(&other), vptr_(&vtable_initializer<T>::vtbl_) {}
/* vtbl_は非テンプレートメンバ変数だが,この中に型情報が埋め込まれている*/
void draw() const
{
vptr_->draw(this_);
}
};
// staticメンバ変数の初期化
template <class T>
drawable::vtable drawable::vtable_initializer<T>::vtbl_ = {
&drawable::vtable_initializer<T>::draw
};
struct circle {
void draw() const
{
std::cout << "Drawing Circle" << std::endl;
}
};
struct square {
void draw() const
{
std::cout << "Drawing Square" << std::endl;
}
};
void draw(drawable a)
{
a.draw();
}
int main()
{
circle c;
draw(c);
square s;
draw(s);
return 0;
}