title: Boost 1.74.0 Asio Executor Migration Issues
body: <p>Related (but not the problem), I am trying to get a <a href="https://github.com/equalitie/cpp-upnp" rel="nofollow noreferrer">UPnP library</a> to work. It <a href="https://github.com/equalitie/cpp-upnp/blob/5ba742accded434523c6b9dabae72d062927ead8/cppupnp-config.cmake#L5-L15" rel="nofollow noreferrer">appears to be targeted to Boost 1.71.0</a>. However, my project uses Boost 1.74.0. So I thought it should be fairly easy to migrate.</p>
  <p>But it seems that something significant changed with asio's executors in Boost 1.74.0. It's not clear to me what changed or how to migrate from 1.73.x to 1.74.0. I intend to use Boost Asio for additional parts of the project so I need to understand what is happening here.</p>
  <p>I think I have trimmed it down to a minimal reproducible code snippet. This snippet <a href="https://gcc.godbolt.org/z/659ncx" rel="nofollow noreferrer">compiles fine with Boost 1.73.0 and GCC 5.5</a>.</p>
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;boost/asio/ip/tcp.hpp&gt;
  #include &lt;boost/asio/executor.hpp&gt;
  
  namespace net = boost::asio;
  using tcp = net::ip::tcp;
  
  void foo(net::executor exec)
  {
      tcp::resolver r{exec};
  }
  </code></pre>
  <p>However, when I <a href="https://gcc.godbolt.org/z/hd4jeh" rel="nofollow noreferrer">change the library to Boost 1.74.0 I then get a compiler error</a> that describes an issue with the executor.</p>
  <p>The error appears to be related to the executor changes. If I try to instantiate a <code>tcp::socket</code> or <code>udp::socket</code> or even a <code>local::stream_protocol::socket</code>, they all result in the same error describing executors.</p>
  <p>I did a brief search on cpplang slack. One comment thread seemed to suggest to use <code>bind_executor</code>. I don't know what that is, but <a href="https://gcc.godbolt.org/z/qnhMEG" rel="nofollow noreferrer">it didn't solve the problem either</a>. Another comment suggested that the <code>execution_context</code> was needed <a href="https://gcc.godbolt.org/z/a146rb" rel="nofollow noreferrer">which also didn't work</a>. There was a lot of discussion about using <code>any_executor</code> but <a href="https://gcc.godbolt.org/z/E33adM" rel="nofollow noreferrer">that also doesn't seem to work</a>.</p>
  <p>So I thought maybe the release notes might include some instructions for migration.</p>
  <p>I saw a paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0443r13.html" rel="nofollow noreferrer"><code>P0443R13</code></a>. Maybe I'll read that later but it's far too dense material to get a quick solution.</p>
  <p>I also saw two papers <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1348r0.html" rel="nofollow noreferrer"><code>P1348R0</code></a> and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1393r0.html" rel="nofollow noreferrer"><code>P1393R0</code></a> both of which are very terse but doesn't appear to be related to the problem I'm encountering.</p>
  <p>The compiler error is described below:</p>
  <pre><code>source&gt;:9:25: error: no matching function for call to 'boost::asio::ip::basic_resolver&lt;boost::asio::ip::tcp&gt;::basic_resolver(&lt;brace-enclosed initializer list&gt;)'
       tcp::resolver r{exec};
                           ^
  </code></pre>
  <p>I understand that the resolver object can't be constructed. The error goes on with several notes and related substitution failure messages</p>
  <ul>
  <li><p>This one clearly describes that it can't convert an execution context to a resolver r-value reference. Makes sense.</p>
  <pre><code>/opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:141:3: note: candidate: boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;::basic_resolver(boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;&amp;&amp;) [with InternetProtocol = boost::asio::ip::tcp; Executor = boost::asio::execution::any_executor&lt;boost::asio::execution::context_as_t&lt;boost::asio::execution_context&amp;&gt;, boost::asio::execution::detail::blocking::never_t&lt;0&gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::blocking::possibly_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::tracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::untracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::fork_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::continuation_t&lt;0&gt; &gt; &gt;]
     basic_resolver(basic_resolver&amp;&amp; other)
     ^
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:141:3: note:   no known conversion for argument 1 from 'boost::asio::executor' to 'boost::asio::ip::basic_resolver&lt;boost::asio::ip::tcp&gt;&amp;&amp;'
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:122:12: 
  </code></pre>
  </li>
  <li><p>This one describes a template substitution failure. It appears to be related to the executor. I don't understand what the failure is.</p>
  <pre><code>/opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:122:12: note: candidate: template&lt;class ExecutionContext&gt; boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;::basic_resolver(ExecutionContext&amp;, typename std::enable_if&lt;std::is_convertible&lt;ExecutionContext&amp;, boost::asio::execution_context&amp;&gt;::value&gt;::type*)
     explicit basic_resolver(ExecutionContext&amp; context,
              ^
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:122:12: note:   template argument deduction/substitution failed:
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp: In substitution of 'template&lt;class ExecutionContext&gt; boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;::basic_resolver(ExecutionContext&amp;, typename std::enable_if&lt;std::is_convertible&lt;ExecutionContext&amp;, boost::asio::execution_context&amp;&gt;::value&gt;::type*) [with ExecutionContext = boost::asio::executor]':
  &lt;source&gt;:9:25:   required from here
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:122:12: error: no type named 'type' in 'struct std::enable_if&lt;false, void&gt;'
  </code></pre>
  </li>
  <li><p>This one also appears to be related to the executor but it can't convert the <code>boost::asio::executor</code> to a <code>boost::asio::execution::any_executor</code> with a bunch of template vomit. This is the constructor that I think <em>should</em> be valid but apparently is not.</p>
  <pre><code>/opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:108:12: note: candidate: boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;::basic_resolver(const executor_type&amp;) [with InternetProtocol = boost::asio::ip::tcp; Executor = boost::asio::execution::any_executor&lt;boost::asio::execution::context_as_t&lt;boost::asio::execution_context&amp;&gt;, boost::asio::execution::detail::blocking::never_t&lt;0&gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::blocking::possibly_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::tracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::untracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::fork_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::continuation_t&lt;0&gt; &gt; &gt;; boost::asio::ip::basic_resolver&lt;InternetProtocol, Executor&gt;::executor_type = boost::asio::execution::any_executor&lt;boost::asio::execution::context_as_t&lt;boost::asio::execution_context&amp;&gt;, boost::asio::execution::detail::blocking::never_t&lt;0&gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::blocking::possibly_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::tracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::untracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::fork_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::continuation_t&lt;0&gt; &gt; &gt;]
     explicit basic_resolver(const executor_type&amp; ex)
              ^
  /opt/compiler-explorer/libs/boost_1_74_0/boost/asio/ip/basic_resolver.hpp:108:12: note:   no known conversion for argument 1 from 'boost::asio::executor' to 'const executor_type&amp; {aka const boost::asio::execution::any_executor&lt;boost::asio::execution::context_as_t&lt;boost::asio::execution_context&amp;&gt;, boost::asio::execution::detail::blocking::never_t&lt;0&gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::blocking::possibly_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::tracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::outstanding_work::untracked_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::fork_t&lt;0&gt; &gt;, boost::asio::execution::prefer_only&lt;boost::asio::execution::detail::relationship::continuation_t&lt;0&gt; &gt; &gt;&amp;}'
  </code></pre>
  </li>
  </ul>
  <p>I see <a href="https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/std_executors.html#boost_asio.std_executors.polymorphic_i_o_executor" rel="nofollow noreferrer">Asio does decribe</a> &quot;<em>This new name may break existing code that directly uses the old polymorphic wrapper, <a href="https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/reference/executor.html" rel="nofollow noreferrer"><code>executor</code></a>.</em>&quot;</p>