Listing 7

template <typename type_vector, typename n>
struct at_v
  : mpl::apply_if<
  mpl::greater<mpl::size<type_vector>, n>,
  mpl::at<type_vector, n>,
  mpl::identity<mpl::void_>
  >
{};
class async_result
{
  template<typename ret, typename params>
  friend class delegate;
public:
  bool is_completed() { return _call->is_completed(); }
  void wait() { _call->wait_completion(); }
private:
  async_result(shared_ptr<simple_call> call) : _call(call) {}
  shared_ptr<simple_call> get_call() const
  { return _call; }
  shared_ptr<simple_call> _call;
};
// bad_async_result - plain std::exception 
template<typename ret, typename params>
class delegate
{
public:
  typedef ret dret;
  typedef params dparams;
  typedef typename at_v<params, mpl::size_t<0> >::type p1;
  // repeat for parameters 2 and higher
  typedef async_callback<ret>* ac_ptr;
  template<typename ptr_obj, typename mem_fun>
    delegate(ptr_obj o, mem_fun m)
  {
    _impl_factory = shared_ptr<impl>(
      new delegate_impl<delegate, ptr_obj, mem_fun>
      (o, m));
  }
  async_result begin_invoke(ac_ptr ac = 0) 
  { 
    impl* i = new_impl(ac);
    (*i)(ac);
    return queue_it(i);
  }
  async_result begin_invoke(p1 par1, ac_ptr ac = 0) 
  {
    impl* i = new_impl(ac);
    (*i)(par1, ac);
    return queue_it(i);
  }
  // repeat begin_invoke for 2 and more parameters
  ret end_invoke(const async_result& ar) 
  {
    shared_ptr<simple_call> sc = ar.get_call();
    calls::iterator it = std::find(_calls.begin(),
      _calls.end(), sc);
    if(it == _calls.end())
      throw bad_async_result();
    sc->wait_completion();
    impl* i = static_cast<impl*>(sc.get());
    return i->result();
  }
private:
  typedef callable<ret, params> impl;
  impl* new_impl(ac_ptr ac = 0) 
  { 
    impl* imp = simple_call::clone(_impl_factory.get());
    imp->deliver_to(ac);
    return imp;
  }
  shared_ptr<simple_call> queue_it(impl* i)
  {
    shared_ptr<simple_call> sc(i);
    work_queue::instance().queue_item(sc);
    _calls.push_back(sc);
    return sc;
  }
  shared_ptr<impl> _impl_factory;
  typedef std::list<shared_ptr<simple_call> > calls;
  calls _calls;
};