function + bindを使ったType Erasure
オブジェクトをboost::anyでメンバに持ち、anyにコピーしたオブジェクトを元の型に変換してbind。
boost::any_cast
メンバ変数の宣言順(初期化順)に注意、obj_が最初。
#include <boost/function.hpp> #include <boost/bind.hpp> #include <boost/any.hpp> class GameScene { boost::any obj_; boost::function<void()> update_func_; boost::function<void()> draw_func_; public: GameScene() {} template <class T> GameScene(const T& obj) : obj_(obj), update_func_(boost::bind(&T::update, boost::any_cast<T>(&obj_))), draw_func_(boost::bind(&T::draw, boost::any_cast<T>(&obj_))) {} template <class T> GameScene& operator=(const T& obj) { obj_ = obj; update_func_ = boost::bind(&T::update, boost::any_cast<T>(&obj_)); draw_func_ = boost::bind(&T::draw, boost::any_cast<T>(&obj_)); return *this; } void update() { update_func_(); } void draw() const { draw_func_(); } bool is_empty() const { return obj_.empty() || update_func_.empty() || draw_func_.empty(); } }; #include <iostream> #include <boost/current_function.hpp> struct Title { void update() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } void draw() const { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } }; struct Game { void update() { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } void draw() const { std::cout << BOOST_CURRENT_FUNCTION << std::endl; } }; int main() { GameScene current_scene = Title(); current_scene.update(); current_scene.draw(); current_scene = Game(); current_scene.update(); current_scene.draw(); }
anyはともかく、functionのコストをいかに下げるかが今後の課題。
自分が使う分には今のままでもいいのだが。