構造体のメンバ変数を定数の値で取得したい
#include <iostream> #include <ctime> #include <boost/assert.hpp> #include <boost/multi_index/member.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/at.hpp> #include <boost/mpl/for_each.hpp> namespace multi_index = boost::multi_index; namespace mpl = boost::mpl; typedef mpl::vector< multi_index::member<std::tm, int, &std::tm::tm_year >, multi_index::member<std::tm, int, &std::tm::tm_mon >, multi_index::member<std::tm, int, &std::tm::tm_mday >, multi_index::member<std::tm, int, &std::tm::tm_hour >, multi_index::member<std::tm, int, &std::tm::tm_min >, multi_index::member<std::tm, int, &std::tm::tm_sec > >::type tm_members_type; typedef mpl::int_<0> year; typedef mpl::int_<1> month; typedef mpl::int_<2> day; typedef mpl::int_<3> hour; typedef mpl::int_<4> minute; typedef mpl::int_<5> second; template<typename index> int& tm_cast(std::tm& st){ return mpl::at<tm_members_type, index>::type()(st); } template<typename index> const int& tm_cast(const std::tm& st){ return mpl::at<tm_members_type, index>::type()(st); } struct print{ print(std::tm & st_) : st(st_){}; template<typename T> void operator ()(const T& rhs) const{ std::cout << rhs(st) << "-"; } private: std::tm& st; }; int main(){ std::tm st; BOOST_ASSERT(( &st.tm_year == &tm_cast<mpl::int_<0> >(st) )); BOOST_ASSERT(( &st.tm_hour == &tm_cast<hour>(st) )); tm_cast<year> (st) = 2010; tm_cast<month> (st) = 12; tm_cast<day> (st) = 25; tm_cast<hour> (st) = 9; tm_cast<minute>(st) = 12; tm_cast<second>(st) = 49; mpl::for_each<tm_members_type>(print(st)); return 0; }
[出力]
2010-12-25-9-12-49-
std::tm の構造体の様に、多くのメンバ変数を持っている場合、for_each 等のループで回したい場合があります。
multi_index::member を使用すれば、メンバ変数へのアドレスを保持することが出来るので、それを利用して、std::tm の変数にアクセスを行っています。
typedef multi_index::member<std::tm, int, &std::tm::tm_year> year_member_type; std::tm st; BOOST_ASSERT(( &st.tm_year == &(year_member_type()(st)) ));
あとは mpl::vector で、使用するメンバ変数を列挙してやれば、コンパイル時に定数で変数にアクセすることが出来ます。
やったね!
C 言語的なイメージとしては、関数ポインタの配列を用意しているとかそんな感じです。
実行時の一時変数なんかでアクセスを行いたい場合は、もうちょっと工夫がいるかな?
以上、黒魔術でした。
[boost]
ver 1.45.0