実体共有型転送関数オブジェクトクラス(仮)

あ,そうか.別にRandom Number Generatorに限らず,pimpl (handle-body idiom)を使った実体(状態)共有のためのファンクタラッパ欲しい状況は結構あるからそ〜ゆ〜汎用転送ファンクタクラスを作ってしまえば良いのだっ!!!作ってみよ.
#作った

#include <boost/mpl/has_xxx.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/tuple/tuple.hpp>

namespace detail{

BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)

template<class F, class R = void>
struct enable_if_has_result_type
  : public boost::enable_if<has_result_type<F>, R>
{ };

template<class F, class R = void>
struct disable_if_has_result_type
  : public boost::disable_if<has_result_type<F>, R>
{ };

}

template<
  class F
, class = typename detail::disable_if_has_result_type<F>::type
>
class shared_function
{
public:
  template<class Sig>
  struct result;
  
  template<class A0>
  struct result< shared_function(A0) >
    : public boost::result_of< F(A0) >
  { };

  template<class A0, class A1>
  struct result< shared_function(A0, A1) >
    : public boost::result_of< F(A0, A1) >
  { };

  template<class A0, class A1, class A2>
  struct result< shared_function(A0, A1, A2) >
    : public boost::result_of< F(A0, A1, A1) >
  { };

  template<class A0, class A1, class A2, class A3>
  struct result< shared_function(A0, A1, A2, A3) >
    : public boost::result_of< F(A0, A1, A1, A3) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4>
  struct result< shared_function(A0, A1, A2, A3, A4) >
    : public boost::result_of< F(A0, A1, A1, A3, A4) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4, class A5>
  struct result< shared_function(A0, A1, A2, A3, A4, A5) >
    : public boost::result_of< F(A0, A1, A1, A3, A4, A5) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4, class A5, class A6>
  struct result< shared_function(A0, A1, A2, A3, A4, A5, A6) >
    : public boost::result_of< F(A0, A1, A1, A3, A4, A5, A6) >
  { };
  
  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7
  >
  struct result< shared_function(A0, A1, A2, A3, A4, A5, A6, A7) >
    : public boost::result_of< F(A0, A1, A1, A3, A4, A5, A6, A7) >
  { };
  
  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7, class A8
  >
  struct result< shared_function(A0, A1, A2, A3, A4, A5, A6, A7, A8) >
    : public boost::result_of< F(A0, A1, A1, A3, A4, A5, A6, A7, A8) >
  { };
  
  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7, class A8, class A9
  >
  struct result< shared_function(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9) >
    : public boost::result_of< F(A0, A1, A1, A3, A4, A5, A6, A7, A8, A9) >
  { };

  // Specializations for "sig." (used in Boost.Lambda)
  template<class Args>
  struct sig;

  template<class A0>
  struct sig<boost::tuples::tuple<shared_function, A0> >
    : public boost::result_of< F(A0 &) >
  { };
  
  template<class A0, class A1>
  struct sig<boost::tuples::tuple<shared_function, A0, A1> >
    : public boost::result_of< F(A0 &, A1 &) >
  { };
  
  template<class A0, class A1, class A2>
  struct sig<boost::tuples::tuple<shared_function, A0, A1, A2> >
    : public boost::result_of< F(A0 &, A1 &, A2 &) >
  { };
  
  template<class A0, class A1, class A2, class A3>
  struct sig<boost::tuples::tuple<shared_function, A0, A1, A2, A3> >
    : public boost::result_of< F(A0 &, A1 &, A2 &, A3 &) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4>
  struct sig<boost::tuples::tuple<shared_function, A0, A1, A2, A3, A4> >
    : public boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4, class A5>
  struct sig<boost::tuples::tuple<shared_function, A0, A1, A2, A3, A4, A5> >
    : public boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &) >
  { };
  
  template<class A0, class A1, class A2, class A3, class A4, class A5, class A6>
  struct sig<boost::tuples::tuple<shared_function, A0, A1, A2, A3, A4, A5, A6> >
    : public boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &) >
  { };
  
  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7
  >
  struct sig<
    boost::tuples::tuple<shared_function, A0, A1, A2, A3, A4, A5, A6, A7>
  >
    : public boost::result_of<
        F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &)
      >
  { };
  
  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7, class A8
  >
  struct sig<
    boost::tuples::tuple<shared_function, A0, A1, A2, A3, A4, A5, A6, A7, A8>
  >
    : public boost::result_of<
        F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &)
      >
  { };
  
  shared_function()
    : p_(new F())
  {
    // This avoids the case F is a pointer to a function.
    BOOST_STATIC_ASSERT((boost::is_class<F>::value));
  }

shared_function(boost::shared_ptr<F> p)
    : p_(p)
  { }

  // Compiler-generated assignment and dtor are fine.
  
  template<class A0>
  typename boost::result_of< F(A0 &) >::type
  operator()(A0 &a0) const
  {
    return (*p_)(a0);
  }

  template<class A0, class A1>
  typename boost::result_of< F(A0 &, A1 &) >::type
  operator()(A0 &a0, A1 &a1) const
  {
    return (*p_)(a0, a1);
  }

  template<class A0, class A1, class A2>
  typename boost::result_of< F(A0 &, A1 &, A2 &) >::type
  operator()(A0 &a0, A1 &a1, A2 &a2) const
  {
    return (*p_)(a0, a1, a2);
  }

  template<class A0, class A1, class A2, class A3>
  typename boost::result_of< F(A0 &, A1 &, A2 &, A3 &) >::type
  operator()(A0 &a0, A1 &a1, A2 &a2, A3 &a3) const
  {
    return (*p_)(a0, a1, a2, a3);
  }

  template<class A0, class A1, class A2, class A3, class A4>
  typename boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &) >::type
  operator()(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) const
  {
    return (*p_)(a0, a1, a2, a3, a4);
  }

  template<class A0, class A1, class A2, class A3, class A4, class A5>
  typename boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &) >::type
  operator()(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5) const
  {
    return (*p_)(a0, a1, a2, a3, a4, a5);
  }

  template<class A0, class A1, class A2, class A3, class A4, class A5, class A6>
  typename boost::result_of< F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &) >::type
  operator()(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6) const
  {
    return (*p_)(a0, a1, a2, a3, a4, a5, a6);
  }

  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7
  >
  typename boost::result_of<
    F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &)
  >::type
  operator()(
    A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7
  ) const
  {
    return (*p_)(a0, a1, a2, a3, a4, a5, a6, a7);
  }

  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7, class A8
  >
  typename boost::result_of<
    F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &)
  >::type
  operator()(
    A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7, A8 &a8
  ) const
  {
    return (*p_)(a0, a1, a2, a3, a4, a5, a6, a7, a8);
  }

  template<
    class A0, class A1, class A2, class A3, class A4
  , class A5, class A6, class A7, class A8, class A9
  >
  typename boost::result_of<
    F(A0 &, A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &, A9 &)
  >::type
  operator()(
    A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4
  , A5 &a5, A6 &a6, A7 &a7, A8 &a8, A9 &a9
  ) const
  {
    return (*p_)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }

private:
  boost::shared_ptr<F> p_;
}; // class shared_function



template<class F>
class shared_function<F, typename detail::enable_if_has_result_type<F>::type>
{
public:
  typedef typename F::result_type result_type;

  shared_function()
    : p_(new F())
  {
    BOOST_STATIC_ASSERT((boost::is_class<F>::value));
  }

  shared_function(boost::shared_ptr<F> p)
    : p_(p)
  { }

  result_type operator()() const
  {
    return (*p_)();
  }
  
private:
  boost::shared_ptr<F> p_;
};

っていうか動くのかこれ?<おぃ
簡単だと思ってたら,The Forwarding Problemとかresult_ofの使い方とかresult_typeの有無によるSFINAEとかいろいろ考えないといけなかった.うげー.
何かわけの分からないもので煙に巻いているけれど,要するにただのshared_ptrのラッパに過ぎないし.戻り値型を計算するためのresultの定義が面倒なだけかも.
#もしかして,引数なしのresult_ofが必ずvoidを返す仕様って「クラステンプレート内のクラステンプレートは外側のクラスを明示的に特殊化しないと明示的に特殊化できない」っつー仕様絡み?
#shared_ptrを使う理由が弱いか・・・