真のC++erはコンパイル時に全てを解決する
という人になりたいですねー。日々精進。
昨日大学の講義でソートのアルゴリズムをやってた。そんな物を今更やったって仕方ないので単純選択法でソートをしてみた。コンパイル時に。
以下ずっとソース。
template < typename _Ty, _Ty left, _Ty right, bool = ( left < right ) > struct get_less_; template < typename _Ty, _Ty left, _Ty right > struct get_less_< _Ty, left, right, true > { static const _Ty value = left; }; template < typename _Ty, _Ty left, _Ty right > struct get_less_< _Ty, left, right, false > { static const _Ty value = right; }; template < typename _Ty, _Ty left, _Ty right, bool = ( left > right ) > struct get_greater_; template < typename _Ty, _Ty left, _Ty right > struct get_greater_< _Ty, left, right, true > { static const _Ty value = left; }; template < typename _Ty, _Ty left, _Ty right > struct get_greater_< _Ty, left, right, false > { static const _Ty value = right; }; template < typename _Ty, _Ty ulim, _Ty _, bool = get_less_< _Ty, ulim, _ >::value == ulim > struct ulimit_; template < typename _Ty, _Ty ulim, _Ty _ > struct ulimit_< _Ty, ulim, _, true > { static const _Ty value = _; }; template < typename _Ty, _Ty ulim, _Ty _ > struct ulimit_< _Ty, ulim, _, false > { static const _Ty value = ulim; }; template < typename _Ty, int, _Ty... > struct count_impl_; template < typename _Ty, int _Cnt, _Ty _Head, _Ty... _Tail > struct count_impl_< _Ty, _Cnt, _Head, _Tail... > : public count_impl_< _Ty, _Cnt + 1, _Tail... > {}; template < typename _Ty, int _Cnt > struct count_impl_< _Ty, _Cnt > { static const int cnt = _Cnt; }; template < typename _Ty, _Ty... Args > struct count_ : public count_impl_< _Ty, 0, Args... > {}; template < typename _Ty, int, _Ty, _Ty... > struct count_if_impl_; template < typename _Ty, int _Cnt, _Ty val, _Ty _Head, _Ty... _Tail > struct count_if_impl_< _Ty, _Cnt, val, _Head, _Tail... > : public count_if_impl_< _Ty, val == _Head ? _Cnt + 1 : _Cnt, val, _Tail... > {}; template < typename _Ty, int _Cnt, _Ty val > struct count_if_impl_< _Ty, _Cnt, val > { static const int cnt = _Cnt; }; template < typename _Ty, _Ty val, _Ty... Args > struct count_if_ : public count_if_impl_< _Ty, 0, val, Args... > {}; template < typename _Ty, _Ty... Args > struct get_min_; template < typename _Ty, _Ty _1, _Ty _2, _Ty... Args > struct get_min_< _Ty, _1, _2, Args... > : public get_min_< _Ty, get_less_< _Ty, _1, _2 >::value, Args... > {}; template < typename _Ty, _Ty _1, _Ty _2 > struct get_min_< _Ty, _1, _2 > { static const _Ty value = get_less_< _Ty, _1, _2 >::value; }; template < typename _Ty, _Ty... Args > struct get_max_; template < typename _Ty, _Ty _1, _Ty _2, _Ty... Args > struct get_max_< _Ty, _1, _2, Args... > : public get_max_< _Ty, get_greater_< _Ty, _1, _2 >::value, Args... > {}; template < typename _Ty, _Ty _1, _Ty _2 > struct get_max_< _Ty, _1, _2 > { static const _Ty value = get_greater_< _Ty, _1, _2 >::value; }; template < bool, typename _Ty, _Ty, _Ty > struct if_; template < typename _Ty, _Ty true_, _Ty false_ > struct if_< true, _Ty, true_, false_ > { static const _Ty value = true_; }; template < typename _Ty, _Ty true_, _Ty false_ > struct if_< false, _Ty, true_, false_ > { static const _Ty value = false_; }; template < typename _Ty, _Ty, _Ty, _Ty... > struct get_limited_min_impl_; template < typename _Ty, _Ty ulim, _Ty _cur, _Ty _Head, _Ty... _Tail > struct get_limited_min_impl_< _Ty, ulim, _cur, _Head, _Tail... > : public get_limited_min_impl_< _Ty, ulim, if_< ulimit_< _Ty, ulim, _Head >::value == ulim, _Ty, _cur, get_less_< _Ty, _cur, _Head >::value >::value, _Tail... > {}; template < typename _Ty, _Ty ulim, _Ty _cur > struct get_limited_min_impl_< _Ty, ulim, _cur > { static const _Ty value = ulimit_< _Ty, ulim, _cur >::value; }; template < typename _Ty, _Ty ulim, _Ty... Args > struct get_limited_min_ : public get_limited_min_impl_< _Ty, ulim, get_max_< _Ty, Args... >::value, Args... > {}; template < typename _Ty, int _Cnt, int _end, _Ty up_value, int same_cnt, _Ty... Args > struct sort_impl_ : public sort_impl_< _Ty, _Cnt + 1, _end, up_value, same_cnt - 1, Args... > { static const _Ty value = up_value; }; template < int _Cnt, typename _Ty, _Ty up_value, _Ty... Args > struct sort_impl_< _Ty, _Cnt, _Cnt, up_value, 0, Args... > { static const int cnt = _Cnt; }; template < typename _Ty, int _end, _Ty up_value, int same_cnt, _Ty... Args > struct sort_impl_< _Ty, 0, _end, up_value, same_cnt, Args... > : public sort_impl_< _Ty, 1, _end, up_value, count_if_< _Ty, up_value, Args... >::cnt - 1, Args... > { static const _Ty value = up_value; }; template < typename _Ty, int _Cnt, int _end, _Ty up_value, _Ty... Args > struct sort_impl_< _Ty, _Cnt, _end, up_value, 0, Args... > : public sort_impl_< _Ty, _Cnt + 1, _end, get_limited_min_< _Ty, up_value, Args... >::value, count_if_< _Ty, get_limited_min_< _Ty, up_value, Args... >::value, Args... >::cnt - 1, Args... > { static const _Ty value = get_limited_min_< _Ty, up_value, Args... >::value; }; template < typename _Ty, _Ty... Args > struct sort_ : public sort_impl_< _Ty, 0, count_< _Ty, Args... >::cnt, get_min_< _Ty, Args... >::value, count_if_< int, get_min_< _Ty, Args... >::value, Args... >::cnt, Args... > {}; template < int idx, typename _Ty, _Ty up_value, int same_cnt, _Ty... Args > inline auto get_impl_( const sort_impl_< _Ty, idx, count_< _Ty, Args... >::cnt, up_value, same_cnt, Args... > & ) -> _Ty { return sort_impl_< _Ty, idx, count_< _Ty, Args... >::cnt, up_value, same_cnt, Args... >::value; } template < int idx, typename _Ty, _Ty... Args > inline auto get_( const sort_< _Ty, Args... > &s ) -> _Ty { return get_impl_< idx >( s ); } template < typename _Ty, _Ty... Args > inline auto size_( const sort_< _Ty, Args... > & ) -> int { return sort_< _Ty, Args... >::cnt; } template < int idx, int size, typename _Ty > struct push_back_impl_ { template < typename _Container, _Ty up_value, int same_cnt, _Ty...Args > inline auto operator()( _Container &c, const sort_impl_< _Ty, idx, size, up_value, same_cnt, Args... > &s ) -> void { c.push_back( get_impl_< idx >( s ) ); push_back_impl_< idx + 1, size, _Ty >()( c, s ); } }; template < int idx, typename _Ty > struct push_back_impl_< idx, idx, _Ty > { template < typename _Container, _Ty up_value, int same_cnt, _Ty... Args > inline auto operator()( _Container &, const sort_impl_< _Ty, idx, idx, up_value, same_cnt, Args... > & ) -> void {} }; template < typename _Container, typename _Ty, _Ty... Args > inline auto push_back_( _Container &c, const sort_< _Ty, Args... > &s ) -> void { push_back_impl_< 0, count_< _Ty, Args... >::cnt, _Ty >()( c, s ); } #include <iostream> #include <vector> using namespace std; int main( void ) { sort_< int, 10, 4, 8, 0, 0, 2 > list; vector< int > v; push_back_( v, list ); for ( auto itr = v.begin(), end = v.end(); itr != end; ++itr ) { cout << *itr << endl; } return 0; }
これ意外とむずかった。ちなみにvariadic template arguments使ってるのでC++0x対応必須です。0xの新しいクラスとか使ったらもっとスマートになるだろうな。勉強しよう。