Skip to content

asio integration not working on mac os x/ clang 19 C++ stdlib #1724

@jessmorecroft

Description

@jessmorecroft

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions