Boost.TypeErasure でタスク処理
C++ タスク処理といえば、継承を使用した多態性で実装するのが一般的(だと思う)のですが、Boost.TypeErasure でちょっと実装してみました。
[ソース]
#include <boost/type_erasure/builtin.hpp> #include <boost/type_erasure/operators.hpp> #include <boost/type_erasure/iterator.hpp> #include <boost/type_erasure/callable.hpp> #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/relaxed_match.hpp> #include <boost/type_erasure/member.hpp> #include <boost/mpl/vector.hpp> #include <vector> #include <string> BOOST_TYPE_ERASURE_MEMBER((has_init), init, 0) BOOST_TYPE_ERASURE_MEMBER((has_update), update, 1) BOOST_TYPE_ERASURE_MEMBER((has_render), render, 1) struct counter{ void init(){ count = 0; } bool update(int frame){ if( frame % 2 == 0 ){ ++count; } return count < max; } void render(std::ostream& os) const{ os << name << ":" << count << std::endl; } std::string name; int max; int count; }; struct homu{ void init(){} bool update(int){ ++count; return true; } void render(std::ostream& os) const{ for(int n = 0 ; n < count ; ++n){ os << "homu"; } os << std::endl; } int count = 0; }; struct frame_counter{ void init(){ counter = 0; } bool update(int){ ++counter; return true; } void render(std::ostream& os) const{ os << "frame: " << counter << std::endl; } int& counter; }; int main(){ namespace te = boost::type_erasure; namespace mpl = boost::mpl; typedef boost::mpl::vector< ::has_init<void()>, ::has_update<bool(int)>, ::has_render<void(std::ostream&)>, te::copy_constructible<> > task_requires; typedef te::any<task_requires> task_concept; std::vector<task_concept> tasks; int frame_count = 0; tasks.emplace_back(frame_counter{frame_count}); tasks.emplace_back(counter{"homu", 5, 0}); tasks.emplace_back(counter{"mado", 42, 0}); tasks.emplace_back(counter{"mami", 15, 0}); tasks.emplace_back(counter{"saya", 9, 0}); tasks.emplace_back(counter{"an", 25, 0}); tasks.emplace_back(homu{}); for(auto&& x : tasks){ x.init(); } while(1){ system("cls"); for(auto&& x : tasks){ if(!x.update(frame_count) ){ x.init(); } x.render(std::cout); } } return 0; }
[出力例]
homu:3 mado:13 mami:13 saya:4 an:13 homuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomuhomu
だいぶ素直に、すっきりとした実装になっていますね。
メンバ関数の引数はコンパイル時に決定する必要がありますが、そこも Boost.TypeErasure を使用すれば、もうちょっと高い抽象化を実現することが出きそうですね。
(Boost.TypeErasure を使用するオーバーヘッドが気になるけど。
いくつか C++11 の機能を使っていますが、基本的には C++03 でも動作するはず。