-
Notifications
You must be signed in to change notification settings - Fork 224
Description
I have a NIX setup where my Linux GCC (15) and Clang (21) builds are succeeding, but my Mac OS Clang build (21, but using Apple Clang 19 stdlib) is not. This is when using boost beast. After much hair pulling I believe this may be due to a C++ stdlib feature missing in Clang 19, that the asio integration is effectively relying on. I have tried mightily to use the latest Clang C++ stdlib but have been unsuccessful so far.
Code causing the issue:
mWs.async_accept(asioexec::use_sender);
where mWs is boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>
Compile error:
/nix/store/qk20nysrc2170f1mal5k6r0axqn6jmfj-clang-wrapper-21.1.2/bin/clang++ ........... -isystem /nix/store/1a05xixrdmk175drdln3w047x3dxfr7l-libcxx-19.1.2+apple-sdk-15.5/include/c++/v1 .......
In file included from /Users/jessmorecroft/Work/repo/myapps/api/wsServer.cpp:5:
In file included from /nix/store/yfxsmji6f3jnbdxiakxfiyzk8pygggmn-stdexec-0.11.0/include/asioexec/use_sender.hpp:28:
/nix/store/yfxsmji6f3jnbdxiakxfiyzk8pygggmn-stdexec-0.11.0/include/asioexec/completion_token.hpp:100:14: error: rvalue reference to type 'boost::system::error_code' cannot bind to lvalue of type 'boost::system::error_code'
100 | return static_cast<U&&>(u);
| ^~~~~~~~~~~~~~~~~~~
/nix/store/yfxsmji6f3jnbdxiakxfiyzk8pygggmn-stdexec-0.11.0/include/asioexec/completion_token.hpp:112:27: note: in instantiation of function template specialization 'asioexec::detail::completion_token::convert<boost::system::error_code, boost::system::error_code &>' requested here
112 | completion_token::convert<std::tuple_element_t<Ns, Tuple>>(static_cast<Args&&>(args))...);
| ^
Following to this line in completion_token.hpp, I note this code, and that the "else" section is being exercised due to my use of Clang 19 no doubt.
#ifdef __cpp_lib_reference_from_temporary
(std::is_convertible_v<U &&, T &&> && !std::reference_converts_from_temporary_v<T &&, U &&>)
#else
(
// Just using is_base_of_v is insufficient because it always reports false for built-in types
(std::is_base_of_v<std::remove_cvref_t<T>, std::remove_cvref_t<U>>
|| std::is_same_v<std::remove_cvref_t<T>, std::remove_cvref_t<U>>)
&&
// The returned type must be at least as cv-qualified as the input type (it can be more cv-qualified)
at_least_as_qualified_v<std::remove_reference_t<T>, std::remove_reference_t<U>>
&& (
// Reference type must agree except...
(std::is_lvalue_reference_v<T> == std::is_lvalue_reference_v<T>) ||
// ...special rules for const& which allows rvalues to bind thereto
(std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) ))
#endif
constexpr T&& convert(U&& u) noexcept {
return static_cast<U&&>(u);
}
Presumably there is something in the else logic that is not quite working in this situation. When (on Linux) i'm using Clang 21 or GCC 15, the compile exercises the "if" block and succeeds.