title: How do I write a custom Boost ASIO completion token, as_expected, that yields a std::expected (tl::expected)?
body: <p>I want to write a custom completion token for asio, like <a href="https://think-async.com/Asio/asio-1.22.2/doc/asio/overview/composition/token_adapters.html#asio.overview.composition.token_adapters.as_tuple" rel="nofollow noreferrer"><code>asio::experimental::use_tuple</code></a>, but which actually returns a <a href="https://github.com/TartanLlama/expected" rel="nofollow noreferrer"><code>tl::expected</code></a>.</p>
  <p>The usage would be like:</p>
  <pre class="lang-cpp prettyprint-override"><code>asio::awaitable&lt;void&gt; echo(tcp::socket socket) {
    char data[1024];
    for (;;) {
      tl::expected&lt;std::size_t&gt; result = co_await socket.async_read_some(
          asio::buffer(data), as_expected(asio::use_awaitable));
      if (result.has_value()) {
        // success
      }
  
      // ...
    }
  }
  </code></pre>
  <p>I'm following <a href="https://cppalliance.org/richard/2021/10/10/RichardsOctoberUpdate.html" rel="nofollow noreferrer">Richard Hodges's article about creating a custom timeout completion token</a> to get some of the boilerplate right but am running into trouble.</p>
  <p>I'm stuck on writing the initiation function object. How do I call the underlying <code>Initiation</code> correctly, transform the result of the completion handler, and give it my wrapped <code>CompletionHandler</code>?</p>
  <p>Here's what I have so far (<code>expected_initiation</code> is where I am stuck):</p>
  <pre class="lang-cpp prettyprint-override"><code>// token type
  template &lt;typename CompletionToken&gt;
  struct expected_token {
    CompletionToken&amp; token;
  };
  
  // initiation function
  template &lt;typename... Signatures&gt;
  struct expected_initiation {
    template &lt;typename CompletionHandler, typename Initiation,
              typename... InitArgs&gt;
    void operator()(CompletionHandler handler, std::chrono::milliseconds timeout,
                    Initiation&amp;&amp; initiation, InitArgs&amp;&amp;... init_args) {
      auto ex = asio::get_associated_executor(
          handler, asio::get_associated_executor(initiation));
  
      // is this bind_executor right? how do I transform the output and call
      // handler()?
      asio::bind_executor(ex, [&amp;](auto&amp;&amp; token) {
        return asio::async_initiate&lt;decltype(token), Signatures...&gt;(
            std::forward&lt;Initiation&gt;(initiation), token,
            std::forward&lt;InitArgs&gt;(init_args)...);
      })
    }
  };
  
  // specialization
  template &lt;typename InnerCompletionToken, typename... Signatures&gt;
  struct asio::async_result&lt;expected_token&lt;InnerCompletionToken&gt;, Signatures...&gt; {
    template &lt;typename Initiation, typename... InitArgs&gt;
    static auto initiate(Initiation&amp;&amp; init,
                         expected_token&lt;InnerCompletionToken&gt; t,
                         InitArgs&amp;&amp;... init_args) {
      return asio::async_initiate&lt;InnerCompletionToken, Signatures...&gt;(
          expected_initiation&lt;Signatures...&gt;{}, t.token,
          std::forward&lt;Initiation&gt;(init), std::forward&lt;InitArgs&gt;(init_args)...)
    }
  };
  
  template &lt;typename CompletionToken&gt;
  auto as_expected(CompletionToken&amp;&amp; token) {
    return expected_token&lt;CompletionToken&gt;{token};
  }
  </code></pre>
  <p>I'm worried I'm on the wrong path. I tried to look at the source of <code>experimental::as_tuple</code>, but it was beyond me and looked much more complicated than my attempt, so I wonder if Richard's article is less applicable than I thought, since I'm modifying the completion handler's signature with my token.</p>
  <p>Edit: There's a lot more to this than I thought. To transform the completion signature like this, I think I need to do something like use_future does and specialize for a bunch of signatures:</p>
  <pre><code>// Helper template to choose the appropriate concrete promise handler
  // implementation based on the supplied completion signature.
  template &lt;typename&gt; class promise_handler_selector;
  
  template &lt;&gt;
  class promise_handler_selector&lt;void()&gt;
    : public promise_handler_0 {};
  
  template &lt;&gt;
  class promise_handler_selector&lt;void(asio::error_code)&gt;
    : public promise_handler_ec_0 {};
  
  template &lt;&gt;
  class promise_handler_selector&lt;void(std::exception_ptr)&gt;
    : public promise_handler_ex_0 {};
  
  template &lt;typename Arg&gt;
  class promise_handler_selector&lt;void(Arg)&gt;
    : public promise_handler_1&lt;Arg&gt; {};
  
  template &lt;typename Arg&gt;
  class promise_handler_selector&lt;void(asio::error_code, Arg)&gt;
    : public promise_handler_ec_1&lt;Arg&gt; {};
  
  template &lt;typename Arg&gt;
  class promise_handler_selector&lt;void(std::exception_ptr, Arg)&gt;
    : public promise_handler_ex_1&lt;Arg&gt; {};
  
  #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  
  template &lt;typename... Arg&gt;
  class promise_handler_selector&lt;void(Arg...)&gt;
    : public promise_handler_n&lt;std::tuple&lt;Arg...&gt; &gt; {};
  
  template &lt;typename... Arg&gt;
  class promise_handler_selector&lt;void(asio::error_code, Arg...)&gt;
    : public promise_handler_ec_n&lt;std::tuple&lt;Arg...&gt; &gt; {};
  
  template &lt;typename... Arg&gt;
  class promise_handler_selector&lt;void(std::exception_ptr, Arg...)&gt;
    : public promise_handler_ex_n&lt;std::tuple&lt;Arg...&gt; &gt; {};
  </code></pre>
  <p>This may be well over my head.</p>