Boost.Variantについて調べていたらすごいものを見つけてしまった。
http://archives.free.net.ph/message/20090406.185710.d34aa406.el.html
こういうvariantがあったときに
variant< int , pair<int,double> , pair<int,int> , pair<double,int> > var;
Visitorを書かないといけないのはめんどくさい。
そこで、Vairantにどんな型が格納されているかパターンマッチしてしまえ、というライブラリの提案がかなり前にあったようです。
switch_(var) |= case_< pair<_1,_1> >(...) // matches pair<int,int> |= case_< pair<int,_> >(...) // matches pair<int,*> |= case_< pair<_,_> >(...) // matches pair<*,*> |= case_< int >(...) ;
Sandboxにあるコードが古くて、Boost 1.43.0で動かすのに苦戦しましたが、こんな感じで使えました。
#include <iostream> #include <utility> #include <boost/variant.hpp> #include <boost/type_switch.hpp> #include <boost/mpl/arg.hpp> using namespace boost::type_switch; using std::pair; using namespace boost::mpl::placeholders; struct same_pair { template <class T, class U> void operator()(const std::pair<T, U>& x) const { std::cout << "same pair" << std::endl; } }; struct first_int { template <class T, class U> void operator()(const std::pair<T, U>& x) const { std::cout << "first int" << std::endl; } }; struct int_func { void operator()(int x) const { std::cout << "int_func" << std::endl; } }; struct default_func { template <class T> void operator()(const T& x) const { std::cout << "default_func" << std::endl; } }; typedef boost::variant< int, pair<int, double>, pair<int, int>, pair<double, int> > type; void f(type var) { switch_(var) |= case_< pair<_1, _1> >(same_pair()) // pair<int, int>にマッチ |= case_< pair<int, _> >(first_int()) // pair<int, *>にマッチ |= case_< int >(int_func()) // intにマッチ |= default_(default_func()) // その他 ; } int main() { f(std::make_pair<int, int>(1, 2)); // same_pair f(std::make_pair<int, double>(1, 3.14)); // same_pair...ん? f(3); // int_func }
使い方間違ってるのかもしれない。
しかし、これには夢がある。