再帰算術メタ関数の再帰停止条件

a(n) = a(n-1), a(0) = 1で定義される簡単な数列を模した算術メタ関数を作ろうとした.今回,static constな定数(value)を内部に持たずに,あくまでメタ関数としてのみの機能(type)を提供するメタ関数を作ることにこだわってみた.なので,入力・出力はboost::mpl::int_を想定.要するに「型->型」のみにこだわっている.

// 漸化式a(n) = a(n-1)を表現するメタ関数
template<class T>
struct a
{
  typedef
    typename a<
      typename boost::mpl::minus<
        T,
        boost::mpl::int_<1>
      >::type
    >::type
    type
    ;
};

// 再帰停止条件a(0) = 1
template<>
struct a<boost::mpl::int_<0> >
{
  typedef boost::mpl::int_<1> type;
};

ところがこれがうまく動かない.(少なくともVC++7.1では)
色々試行錯誤した結果,再帰停止条件が厳しすぎる(boost::mpl::int_<0>の特殊化にドンピシャで一致しないといけない)のかと思って,SFINAEで若干緩い停止条件を書いてみた.そしたらうまく動いた.

// a(n) = a(n-1)
template<class T, class = void>
struct a
{
  typedef
    typename a<
      typename boost::mpl::minus<
        T,
        boost::mpl::int_<1>
      >::type
    >::type
    type
    ;
};

// a(0) = 1
template<class T>
struct a<
  T,
  typename boost::enable_if<typename boost::mpl::equal_to<T, boost::mpl::int_<0> >::type>::type
>
{
  typedef boost::mpl::int_<1> type;
};

int main()
{
  std::cout << a<boost::mpl::int_<10> >::type::value << std::endl; // a(10),つまり1
}

(゜д゜)ウマー.