Open RobertLeahy opened 11 months ago
@RobertLeahy I'm having the same issue. Did you find a workaround?
Declaring (but not defining) the rvalue-qualified operator()
allows the code to compile since it satisfies the compile time check. Since the rvalue-qualified version will never be invoked (assuming the asynchronous operation is correctly implemented) this effectively works around the issue.
Modifying the example from the issue so it builds in C++20:
#include <boost/asio.hpp>
#include <system_error>
using completion_signature = void(std::error_code);
using progress_signature = void(int) &;
struct completion_handler {
void operator()(std::error_code&&) && {
// TODO: Actual implementation here
}
void operator()(int&&) & {
// TODO: Actual implementation here
}
// Never evaluated, presence just allows code
// to compile
void operator()(int&&) &&;
};
template<typename CompletionToken>
decltype(auto) async_operation(CompletionToken&& token) {
return boost::asio::async_initiate<
CompletionToken,
completion_signature,
progress_signature>(
[](auto h) { },
token);
}
int main() {
async_operation(completion_handler{});
}
Builds in C++17 but not C++20. Seems ref-qualification is stripped away at some point in the process of trying to call
async_result::initiate
and therefore once concept checking kicks in the build fails since thestd::is_invocable_v<completion_handler, int>
isfalse
(which should be fine since the matching completion signature is lvalue-qualified and thereforestd::is_invocable_v<completion_handler&, int>
is what should be checked).Compiler explorer reproduction.