にゃははー

はへらー

真の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の新しいクラスとか使ったらもっとスマートになるだろうな。勉強しよう。