Invoke completion handlers as rvalue references.
diff --git a/asio/include/asio/detail/bind_handler.hpp b/asio/include/asio/detail/bind_handler.hpp
index 7151050..1b13235 100644
--- a/asio/include/asio/detail/bind_handler.hpp
+++ b/asio/include/asio/detail/bind_handler.hpp
@@ -28,6 +28,113 @@
 namespace asio {
 namespace detail {
 
+template <typename Handler>
+class binder0
+{
+public:
+  template <typename T>
+  binder0(int, ASIO_MOVE_ARG(T) handler)
+    : handler_(ASIO_MOVE_CAST(T)(handler))
+  {
+  }
+
+  binder0(Handler& handler)
+    : handler_(ASIO_MOVE_CAST(Handler)(handler))
+  {
+  }
+
+#if defined(ASIO_HAS_MOVE)
+  binder0(const binder0& other)
+    : handler_(other.handler_)
+  {
+  }
+
+  binder0(binder0&& other)
+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_))
+  {
+  }
+#endif // defined(ASIO_HAS_MOVE)
+
+  void operator()()
+  {
+    ASIO_MOVE_CAST(Handler)(handler_)();
+  }
+
+  void operator()() const
+  {
+    handler_();
+  }
+
+//private:
+  Handler handler_;
+};
+
+template <typename Handler>
+inline asio_handler_allocate_is_deprecated
+asio_handler_allocate(std::size_t size,
+    binder0<Handler>* this_handler)
+{
+#if defined(ASIO_NO_DEPRECATED)
+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
+  return asio_handler_allocate_is_no_longer_used();
+#else // defined(ASIO_NO_DEPRECATED)
+  return asio_handler_alloc_helpers::allocate(
+      size, this_handler->handler_);
+#endif // defined(ASIO_NO_DEPRECATED)
+}
+
+template <typename Handler>
+inline asio_handler_deallocate_is_deprecated
+asio_handler_deallocate(void* pointer, std::size_t size,
+    binder0<Handler>* this_handler)
+{
+  asio_handler_alloc_helpers::deallocate(
+      pointer, size, this_handler->handler_);
+#if defined(ASIO_NO_DEPRECATED)
+  return asio_handler_deallocate_is_no_longer_used();
+#endif // defined(ASIO_NO_DEPRECATED)
+}
+
+template <typename Handler>
+inline bool asio_handler_is_continuation(
+    binder0<Handler>* this_handler)
+{
+  return asio_handler_cont_helpers::is_continuation(
+      this_handler->handler_);
+}
+
+template <typename Function, typename Handler>
+inline asio_handler_invoke_is_deprecated
+asio_handler_invoke(Function& function,
+    binder0<Handler>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+#if defined(ASIO_NO_DEPRECATED)
+  return asio_handler_invoke_is_no_longer_used();
+#endif // defined(ASIO_NO_DEPRECATED)
+}
+
+template <typename Function, typename Handler>
+inline asio_handler_invoke_is_deprecated
+asio_handler_invoke(const Function& function,
+    binder0<Handler>* this_handler)
+{
+  asio_handler_invoke_helpers::invoke(
+      function, this_handler->handler_);
+#if defined(ASIO_NO_DEPRECATED)
+  return asio_handler_invoke_is_no_longer_used();
+#endif // defined(ASIO_NO_DEPRECATED)
+}
+
+template <typename Handler>
+inline binder0<typename decay<Handler>::type> bind_handler(
+    ASIO_MOVE_ARG(Handler) handler)
+{
+  return binder0<typename decay<Handler>::type>(
+      0, ASIO_MOVE_CAST(Handler)(handler));
+}
+
 template <typename Handler, typename Arg1>
 class binder1
 {
@@ -61,7 +168,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_));
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_));
   }
 
   void operator()() const
@@ -178,7 +285,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_),
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_),
         static_cast<const Arg2&>(arg2_));
   }
 
@@ -302,7 +409,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_),
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_),
         static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));
   }
 
@@ -435,7 +542,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_),
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_),
         static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
         static_cast<const Arg4&>(arg4_));
   }
@@ -578,7 +685,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_),
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_),
         static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
         static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));
   }
@@ -691,7 +798,8 @@
 
   void operator()()
   {
-    handler_(ASIO_MOVE_CAST(Arg1)(arg1_));
+    ASIO_MOVE_CAST(Handler)(handler_)(
+        ASIO_MOVE_CAST(Arg1)(arg1_));
   }
 
 //private:
@@ -766,7 +874,7 @@
 
   void operator()()
   {
-    handler_(static_cast<const Arg1&>(arg1_),
+    ASIO_MOVE_CAST(Handler)(handler_)(static_cast<const Arg1&>(arg1_),
         ASIO_MOVE_CAST(Arg2)(arg2_));
   }
 
diff --git a/asio/include/asio/detail/work_dispatcher.hpp b/asio/include/asio/detail/work_dispatcher.hpp
index 836605f..9ece501 100644
--- a/asio/include/asio/detail/work_dispatcher.hpp
+++ b/asio/include/asio/detail/work_dispatcher.hpp
@@ -16,6 +16,7 @@
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
 #include "asio/detail/config.hpp"
+#include "asio/detail/bind_handler.hpp"
 #include "asio/detail/type_traits.hpp"
 #include "asio/associated_executor.hpp"
 #include "asio/associated_allocator.hpp"
@@ -81,7 +82,8 @@
         asio::prefer(executor_,
           execution::blocking.possibly,
           execution::allocator((get_associated_allocator)(handler_))),
-        ASIO_MOVE_CAST(Handler)(handler_));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(Handler)(handler_)));
   }
 
 private:
@@ -129,7 +131,8 @@
     typename associated_allocator<Handler>::type alloc(
         (get_associated_allocator)(handler_));
     work_.get_executor().dispatch(
-        ASIO_MOVE_CAST(Handler)(handler_), alloc);
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(Handler)(handler_)), alloc);
     work_.reset();
   }
 
diff --git a/asio/include/asio/impl/buffered_read_stream.hpp b/asio/include/asio/impl/buffered_read_stream.hpp
index 808dc0b..695a2b1 100644
--- a/asio/include/asio/impl/buffered_read_stream.hpp
+++ b/asio/include/asio/impl/buffered_read_stream.hpp
@@ -91,7 +91,7 @@
         const std::size_t bytes_transferred)
     {
       storage_.resize(previous_size_ + bytes_transferred);
-      handler_(ec, bytes_transferred);
+      ASIO_MOVE_CAST(ReadHandler)(handler_)(ec, bytes_transferred);
     }
 
   //private:
@@ -313,14 +313,14 @@
       if (ec || storage_.empty())
       {
         const std::size_t length = 0;
-        handler_(ec, length);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(ec, length);
       }
       else
       {
         const std::size_t bytes_copied = asio::buffer_copy(
             buffers_, storage_.data(), storage_.size());
         storage_.consume(bytes_copied);
-        handler_(ec, bytes_copied);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(ec, bytes_copied);
       }
     }
 
diff --git a/asio/include/asio/impl/buffered_write_stream.hpp b/asio/include/asio/impl/buffered_write_stream.hpp
index 4dfecda..bc83cc3 100644
--- a/asio/include/asio/impl/buffered_write_stream.hpp
+++ b/asio/include/asio/impl/buffered_write_stream.hpp
@@ -77,7 +77,7 @@
         const std::size_t bytes_written)
     {
       storage_.consume(bytes_written);
-      handler_(ec, bytes_written);
+      ASIO_MOVE_CAST(WriteHandler)(handler_)(ec, bytes_written);
     }
 
   //private:
@@ -293,7 +293,7 @@
       if (ec)
       {
         const std::size_t length = 0;
-        handler_(ec, length);
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(ec, length);
       }
       else
       {
@@ -306,7 +306,7 @@
         storage_.resize(orig_size + length);
         const std::size_t bytes_copied = asio::buffer_copy(
             storage_.data() + orig_size, buffers_, length);
-        handler_(ec, bytes_copied);
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(ec, bytes_copied);
       }
     }
 
diff --git a/asio/include/asio/impl/co_spawn.hpp b/asio/include/asio/impl/co_spawn.hpp
index 0283507..3f0a9f8 100644
--- a/asio/include/asio/impl/co_spawn.hpp
+++ b/asio/include/asio/impl/co_spawn.hpp
@@ -96,7 +96,7 @@
     (dispatch)(handler_work.get_executor(),
         [handler = std::move(handler), t = std::move(t)]() mutable
         {
-          handler(std::exception_ptr(), std::move(t));
+          std::move(handler)(std::exception_ptr(), std::move(t));
         });
   }
   catch (...)
@@ -107,7 +107,7 @@
     (dispatch)(handler_work.get_executor(),
         [handler = std::move(handler), e = std::current_exception()]() mutable
         {
-          handler(e, T());
+          std::move(handler)(e, T());
         });
   }
 }
@@ -136,7 +136,7 @@
   (dispatch)(handler_work.get_executor(),
       [handler = std::move(handler), e]() mutable
       {
-        handler(e);
+        std::move(handler)(e);
       });
 }
 
diff --git a/asio/include/asio/impl/compose.hpp b/asio/include/asio/impl/compose.hpp
index cd0f0fa..0ec3a69 100644
--- a/asio/include/asio/impl/compose.hpp
+++ b/asio/include/asio/impl/compose.hpp
@@ -348,7 +348,8 @@
     void complete(Args... args)
     {
       this->work_.reset();
-      this->handler_(ASIO_MOVE_CAST(Args)(args)...);
+      ASIO_MOVE_CAST(Handler)(this->handler_)(
+          ASIO_MOVE_CAST(Args)(args)...);
     }
 
 #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
@@ -363,7 +364,7 @@
     void complete()
     {
       this->work_.reset();
-      this->handler_();
+      ASIO_MOVE_CAST(Handler)(this->handler_)();
     }
 
 #define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
@@ -379,7 +380,8 @@
     void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \
     { \
       this->work_.reset(); \
-      this->handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \
+      ASIO_MOVE_CAST(Handler)(this->handler_)( \
+          ASIO_VARIADIC_MOVE_ARGS(n)); \
     } \
     /**/
     ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF)
diff --git a/asio/include/asio/impl/connect.hpp b/asio/include/asio/impl/connect.hpp
index e4614b4..95ce95c 100644
--- a/asio/include/asio/impl/connect.hpp
+++ b/asio/include/asio/impl/connect.hpp
@@ -392,7 +392,8 @@
           ++index_;
         }
 
-        handler_(static_cast<const asio::error_code&>(ec),
+        ASIO_MOVE_CAST(RangeConnectHandler)(handler_)(
+            static_cast<const asio::error_code&>(ec),
             static_cast<const typename Protocol::endpoint&>(
               ec || iter == end ? typename Protocol::endpoint() : *iter));
       }
@@ -598,7 +599,8 @@
           ++iter_;
         }
 
-        handler_(static_cast<const asio::error_code&>(ec),
+        ASIO_MOVE_CAST(IteratorConnectHandler)(handler_)(
+            static_cast<const asio::error_code&>(ec),
             static_cast<const Iterator&>(iter_));
       }
     }
diff --git a/asio/include/asio/impl/defer.hpp b/asio/include/asio/impl/defer.hpp
index 5bf98bd..129d868 100644
--- a/asio/include/asio/impl/defer.hpp
+++ b/asio/include/asio/impl/defer.hpp
@@ -56,7 +56,8 @@
           asio::require(ex, execution::blocking.never),
           execution::relationship.continuation,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -77,7 +78,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex.defer(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 };
 
@@ -121,7 +123,8 @@
           asio::require(ex_, execution::blocking.never),
           execution::relationship.continuation,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -175,7 +178,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex_.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex_.defer(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 
   template <typename CompletionHandler>
diff --git a/asio/include/asio/impl/dispatch.hpp b/asio/include/asio/impl/dispatch.hpp
index e5c55a2..b602f6f 100644
--- a/asio/include/asio/impl/dispatch.hpp
+++ b/asio/include/asio/impl/dispatch.hpp
@@ -53,7 +53,8 @@
         asio::prefer(ex,
           execution::blocking.possibly,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -74,7 +75,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex.dispatch(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 };
 
@@ -117,7 +119,8 @@
         asio::prefer(ex_,
           execution::blocking.possibly,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -170,7 +173,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex_.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex_.dispatch(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 
   template <typename CompletionHandler>
diff --git a/asio/include/asio/impl/post.hpp b/asio/include/asio/impl/post.hpp
index 90b781f..ec96a6c 100644
--- a/asio/include/asio/impl/post.hpp
+++ b/asio/include/asio/impl/post.hpp
@@ -56,7 +56,8 @@
           asio::require(ex, execution::blocking.never),
           execution::relationship.fork,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -77,7 +78,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex.post(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 };
 
@@ -121,7 +123,8 @@
           asio::require(ex_, execution::blocking.never),
           execution::relationship.fork,
           execution::allocator(alloc)),
-        ASIO_MOVE_CAST(CompletionHandler)(handler));
+        asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)));
   }
 
   template <typename CompletionHandler>
@@ -175,7 +178,8 @@
     typename associated_allocator<handler_t>::type alloc(
         (get_associated_allocator)(handler));
 
-    ex_.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
+    ex_.post(asio::detail::bind_handler(
+          ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);
   }
 
   template <typename CompletionHandler>
diff --git a/asio/include/asio/impl/read.hpp b/asio/include/asio/impl/read.hpp
index 4340453..3f7ffe7 100644
--- a/asio/include/asio/impl/read.hpp
+++ b/asio/include/asio/impl/read.hpp
@@ -381,7 +381,8 @@
           max_size = this->check_for_completion(ec, buffers_.total_consumed());
         } while (max_size > 0);
 
-        handler_(ec, buffers_.total_consumed());
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(
+            ec, buffers_.total_consumed());
       }
     }
 
@@ -680,7 +681,8 @@
             break;
         }
 
-        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(ec,
+            static_cast<const std::size_t&>(total_transferred_));
       }
     }
 
@@ -1006,7 +1008,8 @@
             break;
         }
 
-        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(ec,
+            static_cast<const std::size_t&>(total_transferred_));
       }
     }
 
diff --git a/asio/include/asio/impl/read_at.hpp b/asio/include/asio/impl/read_at.hpp
index 1e3e3f8..9198144 100644
--- a/asio/include/asio/impl/read_at.hpp
+++ b/asio/include/asio/impl/read_at.hpp
@@ -239,7 +239,8 @@
           max_size = this->check_for_completion(ec, buffers_.total_consumed());
         } while (max_size > 0);
 
-        handler_(ec, buffers_.total_consumed());
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(
+            ec, buffers_.total_consumed());
       }
     }
 
@@ -538,7 +539,8 @@
             break;
         }
 
-        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(ec,
+            static_cast<const std::size_t&>(total_transferred_));
       }
     }
 
diff --git a/asio/include/asio/impl/read_until.hpp b/asio/include/asio/impl/read_until.hpp
index 0cd312a..2dcde64 100644
--- a/asio/include/asio/impl/read_until.hpp
+++ b/asio/include/asio/impl/read_until.hpp
@@ -916,7 +916,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -1225,7 +1225,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -1542,7 +1542,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -1852,7 +1852,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -2228,7 +2228,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -2540,7 +2540,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -2862,7 +2862,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
@@ -3176,7 +3176,7 @@
           (ec || search_position_ == not_found)
           ? 0 : search_position_;
 
-        handler_(result_ec, result_n);
+        ASIO_MOVE_CAST(ReadHandler)(handler_)(result_ec, result_n);
       }
     }
 
diff --git a/asio/include/asio/impl/redirect_error.hpp b/asio/include/asio/impl/redirect_error.hpp
index a6ef550..d428bc0 100644
--- a/asio/include/asio/impl/redirect_error.hpp
+++ b/asio/include/asio/impl/redirect_error.hpp
@@ -55,7 +55,7 @@
 
   void operator()()
   {
-    handler_();
+    ASIO_MOVE_CAST(Handler)(handler_)();
   }
 
 #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
@@ -66,7 +66,8 @@
   >::type
   operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_MOVE_ARG(Args)... args)
   {
-    handler_(ASIO_MOVE_CAST(Arg)(arg),
+    ASIO_MOVE_CAST(Handler)(handler_)(
+        ASIO_MOVE_CAST(Arg)(arg),
         ASIO_MOVE_CAST(Args)(args)...);
   }
 
@@ -75,7 +76,8 @@
       ASIO_MOVE_ARG(Args)... args)
   {
     ec_ = ec;
-    handler_(ASIO_MOVE_CAST(Args)(args)...);
+    ASIO_MOVE_CAST(Handler)(handler_)(
+        ASIO_MOVE_CAST(Args)(args)...);
   }
 
 #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
@@ -86,13 +88,14 @@
   >::type
   operator()(ASIO_MOVE_ARG(Arg) arg)
   {
-    handler_(ASIO_MOVE_CAST(Arg)(arg));
+    ASIO_MOVE_CAST(Handler)(handler_)(
+        ASIO_MOVE_CAST(Arg)(arg));
   }
 
   void operator()(const asio::error_code& ec)
   {
     ec_ = ec;
-    handler_();
+    ASIO_MOVE_CAST(Handler)(handler_)();
   }
 
 #define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \
@@ -102,7 +105,8 @@
   >::type \
   operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_VARIADIC_MOVE_PARAMS(n)) \
   { \
-    handler_(ASIO_MOVE_CAST(Arg)(arg), \
+    ASIO_MOVE_CAST(Handler)(handler_)( \
+        ASIO_MOVE_CAST(Arg)(arg), \
         ASIO_VARIADIC_MOVE_ARGS(n)); \
   } \
   \
@@ -111,7 +115,8 @@
       ASIO_VARIADIC_MOVE_PARAMS(n)) \
   { \
     ec_ = ec; \
-    handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \
+    ASIO_MOVE_CAST(Handler)(handler_)( \
+        ASIO_VARIADIC_MOVE_ARGS(n)); \
   } \
   /**/
   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)
diff --git a/asio/include/asio/impl/spawn.hpp b/asio/include/asio/impl/spawn.hpp
index 7439d5f..5392195 100644
--- a/asio/include/asio/impl/spawn.hpp
+++ b/asio/include/asio/impl/spawn.hpp
@@ -354,7 +354,7 @@
 
       (data->function_)(yield);
       if (data->call_handler_)
-        (data->handler_)();
+        ASIO_MOVE_CAST(Handler)(data->handler_)();
     }
 
     shared_ptr<spawn_data<Handler, Function> > data_;
diff --git a/asio/include/asio/impl/write.hpp b/asio/include/asio/impl/write.hpp
index c1a6eff..6f0eddf 100644
--- a/asio/include/asio/impl/write.hpp
+++ b/asio/include/asio/impl/write.hpp
@@ -346,7 +346,8 @@
           max_size = this->check_for_completion(ec, buffers_.total_consumed());
         } while (max_size > 0);
 
-        handler_(ec, buffers_.total_consumed());
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(
+            ec, buffers_.total_consumed());
       }
     }
 
@@ -617,7 +618,8 @@
             ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));
         return; default:
         buffers_.consume(bytes_transferred);
-        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(ec,
+            static_cast<const std::size_t&>(bytes_transferred));
       }
     }
 
@@ -910,7 +912,8 @@
             ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));
         return; default:
         buffers_.consume(bytes_transferred);
-        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(ec,
+            static_cast<const std::size_t&>(bytes_transferred));
       }
     }
 
diff --git a/asio/include/asio/impl/write_at.hpp b/asio/include/asio/impl/write_at.hpp
index e9889ef..e5062d5 100644
--- a/asio/include/asio/impl/write_at.hpp
+++ b/asio/include/asio/impl/write_at.hpp
@@ -224,7 +224,8 @@
           max_size = this->check_for_completion(ec, buffers_.total_consumed());
         } while (max_size > 0);
 
-        handler_(ec, buffers_.total_consumed());
+        ASIO_MOVE_CAST(WriteHandler)(handler_)(
+            ec, buffers_.total_consumed());
       }
     }
 
@@ -481,7 +482,7 @@
         const std::size_t bytes_transferred)
     {
       streambuf_.consume(bytes_transferred);
-      handler_(ec, bytes_transferred);
+      ASIO_MOVE_CAST(WriteHandler)(handler_)(ec, bytes_transferred);
     }
 
   //private:
diff --git a/asio/include/asio/ssl/detail/buffered_handshake_op.hpp b/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
index 10c87ee..768bcb7 100644
--- a/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
+++ b/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
@@ -56,7 +56,7 @@
       const asio::error_code& ec,
       const std::size_t& bytes_transferred) const
   {
-    handler(ec, bytes_transferred);
+    ASIO_MOVE_CAST(Handler)(handler)(ec, bytes_transferred);
   }
 
 private:
diff --git a/asio/include/asio/ssl/detail/handshake_op.hpp b/asio/include/asio/ssl/detail/handshake_op.hpp
index 7c328ef..de3b29e 100644
--- a/asio/include/asio/ssl/detail/handshake_op.hpp
+++ b/asio/include/asio/ssl/detail/handshake_op.hpp
@@ -51,7 +51,7 @@
       const asio::error_code& ec,
       const std::size_t&) const
   {
-    handler(ec);
+    ASIO_MOVE_CAST(Handler)(handler)(ec);
   }
 
 private:
diff --git a/asio/include/asio/ssl/detail/read_op.hpp b/asio/include/asio/ssl/detail/read_op.hpp
index d334a69..634ebe9 100644
--- a/asio/include/asio/ssl/detail/read_op.hpp
+++ b/asio/include/asio/ssl/detail/read_op.hpp
@@ -56,7 +56,7 @@
       const asio::error_code& ec,
       const std::size_t& bytes_transferred) const
   {
-    handler(ec, bytes_transferred);
+    ASIO_MOVE_CAST(Handler)(handler)(ec, bytes_transferred);
   }
 
 private:
diff --git a/asio/include/asio/ssl/detail/shutdown_op.hpp b/asio/include/asio/ssl/detail/shutdown_op.hpp
index 6989cc7..8f10894 100644
--- a/asio/include/asio/ssl/detail/shutdown_op.hpp
+++ b/asio/include/asio/ssl/detail/shutdown_op.hpp
@@ -51,11 +51,11 @@
       // The engine only generates an eof when the shutdown notification has
       // been received from the peer. This indicates that the shutdown has
       // completed successfully, and thus need not be passed on to the handler.
-      handler(asio::error_code());
+      ASIO_MOVE_CAST(Handler)(handler)(asio::error_code());
     }
     else
     {
-      handler(ec);
+      ASIO_MOVE_CAST(Handler)(handler)(ec);
     }
   }
 };
diff --git a/asio/include/asio/ssl/detail/write_op.hpp b/asio/include/asio/ssl/detail/write_op.hpp
index 9d12131..02b27df 100644
--- a/asio/include/asio/ssl/detail/write_op.hpp
+++ b/asio/include/asio/ssl/detail/write_op.hpp
@@ -60,7 +60,7 @@
       const asio::error_code& ec,
       const std::size_t& bytes_transferred) const
   {
-    handler(ec, bytes_transferred);
+    ASIO_MOVE_CAST(Handler)(handler)(ec, bytes_transferred);
   }
 
 private: