chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.72k stars 1.19k forks source link

`get_associated_immediate_executor` does not compile for executors with `query_static_constexpr` #1392

Open Tradias opened 7 months ago

Tradias commented 7 months ago

I am working on asio-grpc which implements its own Executor type that has a static-constexpr query for blocking_t but non-static require. Apparently that causes issues when using get_associated_immediate_executor.

Example code:

#include <boost/asio/associated_immediate_executor.hpp>

namespace asio = boost::asio;

struct Executor
{
    constexpr auto require(asio::execution::blocking_t::never_t) const
    {
        return Executor{};
    }

    // removing `static` or `constexpr` here resolves the problem
    static constexpr auto query(asio::execution::blocking_t)
    {
        return asio::execution::blocking_t::never;
    }

    template <class Function>
    void execute(Function&&) const {}

    friend bool operator==(const Executor&, const Executor&) = default;
};

auto test()
{
    return asio::get_associated_immediate_executor([] {}, Executor{});
}

Error message:

/opt/compiler-explorer/libs/boost_1_83_0/boost/asio/associated_immediate_executor.hpp: In instantiation of 'static boost::asio::detail::default_immediate_executor<E, <template-parameter-1-2>, <template-parameter-1-3> >::type boost::asio::detail::default_immediate_executor<E, <template-parameter-1-2>, <template-parameter-1-3> >::get(const E&) [with E = Executor; <template-parameter-1-2> = void; <template-parameter-1-3> = void; type = Executor&&]':
/opt/compiler-explorer/libs/boost_1_83_0/boost/asio/associated_immediate_executor.hpp:132:46:   required from 'static decltype (boost::asio::detail::default_immediate_executor<E>::get(e)) boost::asio::detail::associated_immediate_executor_impl<T, E, <template-parameter-1-3>, <template-parameter-1-4> >::get(const T&, const E&) [with T = test()::<lambda()>; E = Executor; <template-parameter-1-3> = void; <template-parameter-1-4> = void; decltype (boost::asio::detail::default_immediate_executor<E>::get(e)) = Executor&&]'
  132 |     return default_immediate_executor<E>::get(e);
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
/opt/compiler-explorer/libs/boost_1_83_0/boost/asio/associated_immediate_executor.hpp:216:57:   required from 'decltype (boost::asio::associated_immediate_executor<T, Executor>::get(t, ex)) boost::asio::get_associated_immediate_executor(const T&, const Executor&, typename constraint<(is_executor<Executor>::value || execution::is_executor<Executor>::value)>::type) [with T = test()::<lambda()>; Executor = Executor; decltype (associated_immediate_executor<T, Executor>::get(t, ex)) = Executor&&; typename constraint<(is_executor<Executor>::value || execution::is_executor<Executor>::value)>::type = int]'
  216 |   return associated_immediate_executor<T, Executor>::get(t, ex);
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
<source>:26:51:   required from here
   26 |     return asio::get_associated_immediate_executor([] {}, Executor{});
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_83_0/boost/asio/associated_immediate_executor.hpp:57:61: error: cannot bind rvalue reference of type 'boost::asio::detail::default_immediate_executor<Executor, void, void>::type' {aka 'Executor&&'} to lvalue of type 'const Executor'
   57 |     return boost::asio::require(e, execution::blocking.never);
      |                                                             ^
Compiler returned: 1
Tradias commented 2 months ago

Issues persists in Boost 1.84: https://godbolt.org/z/67PExzW5j