Initial implementation of move-enable accept/async_accept.

This commit adds support for the new form of accept and async_accept. In this
form, rather than taking a socket by reference, the newly accepted socket is
returned to the caller/callback as a movable socket object.
diff --git a/asio/include/asio/basic_socket_acceptor.hpp b/asio/include/asio/basic_socket_acceptor.hpp
index 5e3109e..287652d 100644
--- a/asio/include/asio/basic_socket_acceptor.hpp
+++ b/asio/include/asio/basic_socket_acceptor.hpp
@@ -1029,7 +1029,7 @@
    * @code
    * asio::ip::tcp::acceptor acceptor(io_service);
    * ...
-   * asio::ip::tcp::soocket socket(io_service);
+   * asio::ip::tcp::socket socket(io_service);
    * asio::error_code ec;
    * acceptor.accept(socket, ec);
    * if (ec)
@@ -1211,6 +1211,122 @@
     return this->get_service().async_accept(this->get_implementation(), peer,
         &peer_endpoint, ASIO_MOVE_CAST(AcceptHandler)(handler));
   }
+
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Accept a new connection.
+  /**
+   * This function is used to accept a new connection from a peer. The function
+   * call will block until a new connection has been accepted successfully or
+   * an error occurs.
+   *
+   * This overload requires that the Protocol template parameter satisfy the
+   * AcceptableProtocol type requirements.
+   *
+   * @returns A socket object representing the newly accepted connection.
+   *
+   * @throws asio::system_error Thrown on failure.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(acceptor.accept());
+   * @endcode
+   */
+  typename Protocol::socket accept()
+  {
+    asio::error_code ec;
+    typename Protocol::socket peer(
+        this->get_service().accept(
+          this->get_implementation(), 0, 0, ec));
+    asio::detail::throw_error(ec, "accept");
+    return peer;
+  }
+
+  /// Accept a new connection.
+  /**
+   * This function is used to accept a new connection from a peer. The function
+   * call will block until a new connection has been accepted successfully or
+   * an error occurs.
+   *
+   * This overload requires that the Protocol template parameter satisfy the
+   * AcceptableProtocol type requirements.
+   *
+   * @param ec Set to indicate what error occurred, if any.
+   *
+   * @returns On success, a socket object representing the newly accepted
+   * connection. On error, a socket object where is_open() is false.
+   *
+   * @par Example
+   * @code
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(acceptor.accept(ec));
+   * if (ec)
+   * {
+   *   // An error occurred.
+   * }
+   * @endcode
+   */
+  typename Protocol::socket accept(asio::error_code& ec)
+  {
+    return this->get_service().accept(this->get_implementation(), 0, 0, ec);
+  }
+
+  /// Start an asynchronous accept.
+  /**
+   * This function is used to asynchronously accept a new connection. The
+   * function call always returns immediately.
+   *
+   * This overload requires that the Protocol template parameter satisfy the
+   * AcceptableProtocol type requirements.
+   *
+   * @param handler The handler to be called when the accept operation
+   * completes. Copies will be made of the handler as required. The function
+   * signature of the handler must be:
+   * @code void handler(
+   *   const asio::error_code& error, // Result of operation.
+   *   typename Protocol::socket peer // On success, the newly accepted socket.
+   * ); @endcode
+   * Regardless of whether the asynchronous operation completes immediately or
+   * not, the handler will not be invoked from within this function. Invocation
+   * of the handler will be performed in a manner equivalent to using
+   * asio::io_service::post().
+   *
+   * @par Example
+   * @code
+   * void accept_handler(const asio::error_code& error,
+   *     asio::ip::tcp::socket peer)
+   * {
+   *   if (!error)
+   *   {
+   *     // Accept succeeded.
+   *   }
+   * }
+   *
+   * ...
+   *
+   * asio::ip::tcp::acceptor acceptor(io_service);
+   * ...
+   * asio::ip::tcp::socket socket(io_service);
+   * acceptor.async_accept(socket, accept_handler);
+   * @endcode
+   */
+  template <typename MoveAcceptHandler>
+  ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+      void (asio::error_code, typename Protocol::socket))
+  async_accept(ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+  {
+    // If you get an error on the following line it means that your handler does
+    // not meet the documented type requirements for a MoveAcceptHandler.
+    ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+        handler, typename Protocol::socket) type_check;
+
+    return this->get_service().async_accept(this->get_implementation(),
+        static_cast<endpoint_type*>(0),
+        ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
 };
 
 } // namespace asio
diff --git a/asio/include/asio/detail/bind_handler.hpp b/asio/include/asio/detail/bind_handler.hpp
index 7271a79..c01a7ac 100644
--- a/asio/include/asio/detail/bind_handler.hpp
+++ b/asio/include/asio/detail/bind_handler.hpp
@@ -220,6 +220,132 @@
       ASIO_MOVE_CAST(Handler)(handler), arg1, arg2);
 }
 
+#if defined(ASIO_HAS_MOVE)
+
+template <typename Handler, typename Arg1>
+class move_binder1
+{
+public:
+  move_binder1(int, ASIO_MOVE_ARG(Handler) handler,
+      ASIO_MOVE_ARG(Arg1) arg1)
+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),
+      arg1_(ASIO_MOVE_CAST(Arg1)(arg1))
+  {
+  }
+
+  move_binder1(move_binder1&& other)
+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_))
+  {
+  }
+
+  void operator()()
+  {
+    handler_(ASIO_MOVE_CAST(Arg1)(arg1_));
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+};
+
+template <typename Handler, typename Arg1>
+inline void* asio_handler_allocate(std::size_t size,
+    move_binder1<Handler, Arg1>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    move_binder1<Handler, Arg1>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline bool asio_handler_is_continuation(
+    move_binder1<Handler, Arg1>* this_handler)
+{
+  return asio_handler_cont_helpers::is_continuation(
+      this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1>
+inline void asio_handler_invoke(ASIO_MOVE_ARG(Function) function,
+    move_binder1<Handler, Arg1>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+class move_binder2
+{
+public:
+  move_binder2(int, ASIO_MOVE_ARG(Handler) handler,
+      const Arg1& arg1, ASIO_MOVE_ARG(Arg2) arg2)
+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),
+      arg1_(arg1),
+      arg2_(ASIO_MOVE_CAST(Arg2)(arg2))
+  {
+  }
+
+  move_binder2(move_binder2&& other)
+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_))
+  {
+  }
+
+  void operator()()
+  {
+    handler_(static_cast<const Arg1&>(arg1_),
+        ASIO_MOVE_CAST(Arg2)(arg2_));
+  }
+
+//private:
+  Handler handler_;
+  Arg1 arg1_;
+  Arg2 arg2_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void* asio_handler_allocate(std::size_t size,
+    move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+    move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline bool asio_handler_is_continuation(
+    move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  return asio_handler_cont_helpers::is_continuation(
+      this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_invoke(ASIO_MOVE_ARG(Function) function,
+    move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
+}
+
+#endif // defined(ASIO_HAS_MOVE)
+
 } // namespace detail
 
 template <typename Handler, typename Arg1, typename Allocator>
@@ -270,6 +396,59 @@
   }
 };
 
+#if defined(ASIO_HAS_MOVE)
+
+template <typename Handler, typename Arg1, typename Allocator>
+struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>
+{
+  typedef typename associated_allocator<Handler, Allocator>::type type;
+
+  static type get(const detail::move_binder1<Handler, Arg1>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
+  {
+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+  }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
+struct associated_allocator<
+    detail::move_binder2<Handler, Arg1, Arg2>, Allocator>
+{
+  typedef typename associated_allocator<Handler, Allocator>::type type;
+
+  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
+  {
+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+  }
+};
+
+template <typename Handler, typename Arg1, typename Executor>
+struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>
+{
+  typedef typename associated_executor<Handler, Executor>::type type;
+
+  static type get(const detail::move_binder1<Handler, Arg1>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
+  {
+    return associated_executor<Handler, Executor>::get(h.handler_, ex);
+  }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Executor>
+struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>
+{
+  typedef typename associated_executor<Handler, Executor>::type type;
+
+  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
+  {
+    return associated_executor<Handler, Executor>::get(h.handler_, ex);
+  }
+};
+
+#endif // defined(ASIO_HAS_MOVE)
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/handler_type_requirements.hpp b/asio/include/asio/detail/handler_type_requirements.hpp
index 8026278..e62596f 100644
--- a/asio/include/asio/detail/handler_type_requirements.hpp
+++ b/asio/include/asio/detail/handler_type_requirements.hpp
@@ -100,6 +100,16 @@
 template <typename Handler>
 char (&two_arg_handler_test(Handler, ...))[2];
 
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+  -> decltype(
+    sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),
+    ((h)(*a1, ASIO_MOVE_CAST(Arg2)(*a2))),
+    char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
 #  define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
      static_assert(expr, msg);
 
@@ -228,6 +238,33 @@
             asio::detail::lvref<const asio::error_code>()), \
         char(0))> ASIO_UNUSED_TYPEDEF
 
+#define ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+    handler_type, handler, socket_type) \
+  \
+  typedef ASIO_HANDLER_TYPE(handler_type, \
+      void(asio::error_code, socket_type)) \
+    asio_true_handler_type; \
+  \
+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+      sizeof(asio::detail::two_arg_move_handler_test( \
+          asio::detail::rvref< \
+            asio_true_handler_type>(), \
+          static_cast<const asio::error_code*>(0), \
+          static_cast<socket_type*>(0))) == 1, \
+      "MoveAcceptHandler type requirements not met") \
+  \
+  typedef asio::detail::handler_type_requirements< \
+      sizeof( \
+        asio::detail::argbyv( \
+          asio::detail::rvref< \
+            asio_true_handler_type>())) + \
+      sizeof( \
+        asio::detail::lvref< \
+          asio_true_handler_type>()( \
+            asio::detail::lvref<const asio::error_code>(), \
+            asio::detail::rvref<socket_type>()), \
+        char(0))> ASIO_UNUSED_TYPEDEF
+
 #define ASIO_CONNECT_HANDLER_CHECK( \
     handler_type, handler) \
   \
diff --git a/asio/include/asio/detail/impl/reactive_socket_service_base.ipp b/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
index f6cf62a..7c262c2 100644
--- a/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
+++ b/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
@@ -29,7 +29,8 @@
 
 reactive_socket_service_base::reactive_socket_service_base(
     asio::io_service& io_service)
-  : reactor_(use_service<reactor>(io_service))
+  : io_service_(io_service),
+    reactor_(use_service<reactor>(io_service))
 {
   reactor_.init_task();
 }
diff --git a/asio/include/asio/detail/reactive_socket_accept_op.hpp b/asio/include/asio/detail/reactive_socket_accept_op.hpp
index ae6ca42..ea83190 100644
--- a/asio/include/asio/detail/reactive_socket_accept_op.hpp
+++ b/asio/include/asio/detail/reactive_socket_accept_op.hpp
@@ -130,6 +130,70 @@
   Handler handler_;
 };
 
+#if defined(ASIO_HAS_MOVE)
+
+template <typename Protocol, typename Handler>
+class reactive_socket_move_accept_op :
+  private Protocol::socket,
+  public reactive_socket_accept_op_base<typename Protocol::socket, Protocol>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);
+
+  reactive_socket_move_accept_op(io_service& ios, socket_type socket,
+      socket_ops::state_type state, const Protocol& protocol,
+      typename Protocol::endpoint* peer_endpoint, Handler& handler)
+    : Protocol::socket(ios),
+      reactive_socket_accept_op_base<typename Protocol::socket, Protocol>(
+        socket, state, *this, protocol, peer_endpoint,
+        &reactive_socket_move_accept_op::do_complete),
+      handler_(ASIO_MOVE_CAST(Handler)(handler))
+  {
+    handler_work<Handler>::start(handler_);
+  }
+
+  static void do_complete(void* owner, operation* base,
+      const asio::error_code& /*ec*/,
+      std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    reactive_socket_move_accept_op* o(
+        static_cast<reactive_socket_move_accept_op*>(base));
+    ptr p = { asio::detail::addressof(o->handler_), o, o };
+    typename Protocol::socket peer(
+        ASIO_MOVE_CAST(typename Protocol::socket)(*o));
+    handler_work<Handler> w(o->handler_);
+
+    ASIO_HANDLER_COMPLETION((o));
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::move_binder2<Handler, asio::error_code, typename Protocol::socket>
+      handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,
+        ASIO_MOVE_CAST(typename Protocol::socket)(peer));
+    p.h = asio::detail::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      fenced_block b(fenced_block::half);
+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
+      w.complete(handler, handler.handler_);
+      ASIO_HANDLER_INVOCATION_END;
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+#endif // defined(ASIO_HAS_MOVE)
+
 } // namespace detail
 } // namespace asio
 
diff --git a/asio/include/asio/detail/reactive_socket_service.hpp b/asio/include/asio/detail/reactive_socket_service.hpp
index 9566777..4d3c723 100644
--- a/asio/include/asio/detail/reactive_socket_service.hpp
+++ b/asio/include/asio/detail/reactive_socket_service.hpp
@@ -388,8 +388,33 @@
     return ec;
   }
 
-  // Start an asynchronous accept. The peer and peer_endpoint objects
-  // must be valid until the accept's handler is invoked.
+  // Accept a new connection.
+  typename Protocol::socket accept(implementation_type& impl,
+      io_service* peer_io_service, endpoint_type* peer_endpoint,
+      asio::error_code& ec)
+  {
+    typename Protocol::socket peer(
+        peer_io_service ? *peer_io_service : io_service_);
+
+    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+          peer_endpoint ? &addr_len : 0, ec));
+
+    // On success, assign new connection to peer socket object.
+    if (new_socket.get() != invalid_socket)
+    {
+      if (peer_endpoint)
+        peer_endpoint->resize(addr_len);
+      if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+        new_socket.release();
+    }
+
+    return peer;
+  }
+
+  // Start an asynchronous accept. The peer and peer_endpoint objects must be
+  // valid until the accept's handler is invoked.
   template <typename Socket, typename Handler>
   void async_accept(implementation_type& impl, Socket& peer,
       endpoint_type* peer_endpoint, Handler& handler)
@@ -410,6 +435,30 @@
     p.v = p.p = 0;
   }
 
+#if defined(ASIO_HAS_MOVE)
+  // Start an asynchronous accept. The peer_endpoint object must be valid until
+  // the accept's handler is invoked.
+  template <typename Handler>
+  void async_accept(implementation_type& impl,
+      endpoint_type* peer_endpoint, Handler& handler)
+  {
+    bool is_continuation =
+      asio_handler_cont_helpers::is_continuation(handler);
+
+    // Allocate and construct an operation to wrap the handler.
+    typedef reactive_socket_move_accept_op<Protocol, Handler> op;
+    typename op::ptr p = { asio::detail::addressof(handler),
+      op::ptr::allocate(handler), 0 };
+    p.p = new (p.v) op(io_service_, impl.socket_, impl.state_,
+        impl.protocol_, peer_endpoint, handler);
+
+    ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+
+    start_accept_op(impl, p.p, is_continuation, false);
+    p.v = p.p = 0;
+  }
+#endif // defined(ASIO_HAS_MOVE)
+
   // Connect the socket to the specified endpoint.
   asio::error_code connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, asio::error_code& ec)
diff --git a/asio/include/asio/detail/reactive_socket_service_base.hpp b/asio/include/asio/detail/reactive_socket_service_base.hpp
index d30fcae..d252cd2 100644
--- a/asio/include/asio/detail/reactive_socket_service_base.hpp
+++ b/asio/include/asio/detail/reactive_socket_service_base.hpp
@@ -490,6 +490,9 @@
       reactor_op* op, bool is_continuation,
       const socket_addr_type* addr, size_t addrlen);
 
+  // The io_service that owns this socket service.
+  io_service& io_service_;
+
   // The selector that performs event demultiplexing for the service.
   reactor& reactor_;
 };
diff --git a/asio/include/asio/detail/win_iocp_socket_service.hpp b/asio/include/asio/detail/win_iocp_socket_service.hpp
index 0bb6178..7903258 100644
--- a/asio/include/asio/detail/win_iocp_socket_service.hpp
+++ b/asio/include/asio/detail/win_iocp_socket_service.hpp
@@ -457,6 +457,31 @@
     return ec;
   }
 
+  // Accept a new connection.
+  typename Protocol::socket accept(implementation_type& impl,
+      io_service* peer_io_service, endpoint_type* peer_endpoint,
+      asio::error_code& ec)
+  {
+    typename Protocol::socket peer(
+        peer_io_service ? *peer_io_service : get_io_service());
+
+    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+          peer_endpoint ? &addr_len : 0, ec));
+
+    // On success, assign new connection to peer socket object.
+    if (new_socket.get() != invalid_socket)
+    {
+      if (peer_endpoint)
+        peer_endpoint->resize(addr_len);
+      if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+        new_socket.release();
+    }
+
+    return ec;
+  }
+
   // Start an asynchronous accept. The peer and peer_endpoint objects
   // must be valid until the accept's handler is invoked.
   template <typename Socket, typename Handler>
diff --git a/asio/include/asio/socket_acceptor_service.hpp b/asio/include/asio/socket_acceptor_service.hpp
index 9844dc2..a1fe502 100644
--- a/asio/include/asio/socket_acceptor_service.hpp
+++ b/asio/include/asio/socket_acceptor_service.hpp
@@ -276,6 +276,16 @@
     return service_impl_.accept(impl, peer, peer_endpoint, ec);
   }
 
+#if defined(ASIO_HAS_MOVE)
+  /// Accept a new connection.
+  typename Protocol::socket accept(implementation_type& impl,
+      io_service* peer_io_service, endpoint_type* peer_endpoint,
+      asio::error_code& ec)
+  {
+    return service_impl_.accept(impl, peer_io_service, peer_endpoint, ec);
+  }
+#endif // defined(ASIO_HAS_MOVE)
+
   /// Start an asynchronous accept.
   template <typename Protocol1, typename SocketService, typename AcceptHandler>
   ASIO_INITFN_RESULT_TYPE(AcceptHandler,
@@ -294,6 +304,24 @@
     return init.result.get();
   }
 
+#if defined(ASIO_HAS_MOVE)
+  /// Start an asynchronous accept.
+  template <typename MoveAcceptHandler>
+  ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+      void (asio::error_code, typename Protocol::socket))
+  async_accept(implementation_type& impl,
+      endpoint_type* peer_endpoint,
+      ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+  {
+    async_completion<MoveAcceptHandler,
+      void (asio::error_code, typename Protocol::socket)> init(handler);
+
+    service_impl_.async_accept(impl, peer_endpoint, init.handler);
+
+    return init.result.get();
+  }
+#endif // defined(ASIO_HAS_MOVE)
+
 private:
   // Destroy all user-defined handler objects owned by the service.
   void shutdown_service()
diff --git a/asio/src/doc/quickref.xml b/asio/src/doc/quickref.xml
index a7526ec..0a762c2 100644
--- a/asio/src/doc/quickref.xml
+++ b/asio/src/doc/quickref.xml
@@ -346,6 +346,7 @@
           </simplelist>
           <bridgehead renderas="sect3">Type Requirements</bridgehead>
           <simplelist type="vert" columns="1">
+            <member><link linkend="asio.reference.AcceptableProtocol">AcceptableProtocol</link></member>
             <member><link linkend="asio.reference.AcceptHandler">AcceptHandler</link></member>
             <member><link linkend="asio.reference.ComposedConnectHandler">ComposedConnectHandler</link></member>
             <member><link linkend="asio.reference.ConnectHandler">ConnectHandler</link></member>
diff --git a/asio/src/doc/reference.xsl b/asio/src/doc/reference.xsl
index d2dce4b..eb8dc5e 100644
--- a/asio/src/doc/reference.xsl
+++ b/asio/src/doc/reference.xsl
@@ -37,6 +37,7 @@
 [xinclude quickref.xml]
 
 [include requirements/asynchronous_operations.qbk]
+[include requirements/AcceptableProtocol.qbk]
 [include requirements/AcceptHandler.qbk]
 [include requirements/AsyncRandomAccessReadDevice.qbk]
 [include requirements/AsyncRandomAccessWriteDevice.qbk]
diff --git a/asio/src/doc/requirements/AcceptableProtocol.qbk b/asio/src/doc/requirements/AcceptableProtocol.qbk
new file mode 100644
index 0000000..2cd3bf2
--- /dev/null
+++ b/asio/src/doc/requirements/AcceptableProtocol.qbk
@@ -0,0 +1,25 @@
+[/
+ / Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See accompanying
+ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ /]
+
+[section:AcceptableProtocol Acceptable protocol requirements]
+
+An acceptable protocol must meet the requirements for a [link
+asio.reference.Protocol protocol] as well as the additional requirements listed
+below.
+
+In the table below, `X` denotes an acceptable protocol class.
+
+[table AcceptableProtocol requirements
+  [[expression] [return type] [assertion/note\npre/post-conditions]]
+  [
+    [`X::socket`]
+    [`
+    [The type of a socket for the protocol.]
+  ]
+]
+
+[endsect]
diff --git a/asio/src/doc/requirements/MoveAcceptHandler.qbk b/asio/src/doc/requirements/MoveAcceptHandler.qbk
new file mode 100644
index 0000000..c8f6080
--- /dev/null
+++ b/asio/src/doc/requirements/MoveAcceptHandler.qbk
@@ -0,0 +1,41 @@
+[/
+ / Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See accompanying
+ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ /]
+
+[section:MoveAcceptHandler Move accept handler requirements]
+
+A move accept handler must meet the requirements for a [link
+asio.reference.Handler handler]. A value `h` of a move accept handler class
+should work correctly in the expression `h(ec, s)`, where `ec` is an lvalue of
+type `const error_code` and `s` is an lvalue of the nested type
+`Protocol::socket` for the type `Protocol` of the socket class template.
+
+[heading Examples]
+
+A free function as a move accept handler:
+
+  void connect_handler(
+      const asio::error_code& ec,
+      asio::ip::tcp::socket s)
+  {
+    ...
+  }
+
+A move accept handler function object:
+
+  struct connect_handler
+  {
+    ...
+    void operator()(
+        const asio::error_code& ec,
+        asio::ip::tcp::socket s)
+    {
+      ...
+    }
+    ...
+  };
+
+[endsect]
diff --git a/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp b/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp
index 85f1520..7c9a2cb 100644
--- a/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp
+++ b/asio/src/examples/cpp11/echo/async_tcp_echo_server.cpp
@@ -66,8 +66,7 @@
 {
 public:
   server(asio::io_service& io_service, short port)
-    : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
-      socket_(io_service)
+    : acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
   {
     do_accept();
   }
@@ -75,12 +74,12 @@
 private:
   void do_accept()
   {
-    acceptor_.async_accept(socket_,
-        [this](std::error_code ec)
+    acceptor_.async_accept(
+        [this](std::error_code ec, tcp::socket socket)
         {
           if (!ec)
           {
-            std::make_shared<session>(std::move(socket_))->start();
+            std::make_shared<session>(std::move(socket))->start();
           }
 
           do_accept();
@@ -88,7 +87,6 @@
   }
 
   tcp::acceptor acceptor_;
-  tcp::socket socket_;
 };
 
 int main(int argc, char* argv[])
diff --git a/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp b/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp
index 6a071fc..2fff5bf 100644
--- a/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp
+++ b/asio/src/examples/cpp11/echo/blocking_tcp_echo_server.cpp
@@ -47,9 +47,7 @@
   tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
   for (;;)
   {
-    tcp::socket sock(io_service);
-    a.accept(sock);
-    std::thread(session, std::move(sock)).detach();
+    std::thread(session, a.accept()).detach();
   }
 }