asio
asio copied to clipboard
Compilation error for endpoint types with custom sockaddr type
I'm writing a SocketCAN wrapper for ASIO.
Considering the following piece of code (also tested with latest standalone ASIO):
#include <linux/can.h>
#include <boost/asio.hpp>
namespace can {
class endpoint;
class raw {
public:
using endpoint = can::endpoint;
using socket = boost::asio::basic_raw_socket<raw>;
int family() const noexcept { return AF_CAN; }
int type() const noexcept { return SOCK_RAW; }
int protocol() const noexcept { return CAN_RAW; }
};
class endpoint {
public:
using protocol_type = raw;
using data_type = ::sockaddr_can;
endpoint() noexcept {
data_.can_family = AF_CAN;
data_.can_ifindex = 0;
}
protocol_type protocol() const noexcept { return protocol_type(); }
const void *data() const noexcept { return &data_; }
void *data() noexcept { return &data_; }
std::size_t size() const noexcept { return sizeof(data_type); }
void resize(const std::size_t s) {
if (s != size())
throw std::system_error(
std::make_error_code(std::errc::invalid_argument));
}
std::size_t capacity() const noexcept { return sizeof(data_type); }
private:
data_type data_;
};
} // namespace can
int main() {
boost::asio::io_context ctx;
can::raw::socket cansock(ctx, can::raw::endpoint());
ctx.run();
}
The documentation says that an 'endpoint' class should return void *
or const void *
from data()
: https://think-async.com/Asio/asio-1.22.1/doc/asio/reference/Endpoint.html
However, the socket implementation using my custom endpoint class does not seem to allow sockaddr types other than sockaddr
.
I'm getting a compilation failure:
[main] Building folder: foo
[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /code/foo/build --config Debug --target all -j 14 --
[build] Scanning dependencies of target foo
[build] [ 50%] Building CXX object CMakeFiles/foo.dir/main.cpp.o
[build] In file included from /code/foo/libs/asio/asio/include/asio/basic_socket.hpp:38,
[build] from /code/foo/libs/asio/asio/include/asio/basic_datagram_socket.hpp:20,
[build] from /code/foo/libs/asio/asio/include/asio.hpp:26,
[build] from /code/foo/main.cpp:8:
[build] /code/foo/libs/asio/asio/include/asio/detail/reactive_socket_service.hpp: In instantiation of ‘asio::error_code asio::detail::reactive_socket_service<Protocol>::bind(asio::detail::reactive_socket_service<Protocol>::implementation_type&, const endpoint_type&, asio::error_code&) [with Protocol = can::raw; asio::error_code = std::error_code; asio::detail::reactive_socket_service<Protocol>::endpoint_type = can::endpoint]’:
[build] /code/foo/libs/asio/asio/include/asio/basic_socket.hpp:241:29: required from ‘asio::basic_socket<Protocol, Executor>::basic_socket(ExecutionContext&, const endpoint_type&, typename asio::constraint<std::is_convertible<ExecutionContext&, asio::execution_context&>::value>::type) [with ExecutionContext = asio::io_context; Protocol = can::raw; Executor = asio::any_io_executor; asio::basic_socket<Protocol, Executor>::endpoint_type = can::endpoint; typename asio::constraint<std::is_convertible<ExecutionContext&, asio::execution_context&>::value>::type = int]’
[build] /code/foo/libs/asio/asio/include/asio/basic_raw_socket.hpp:202:57: required from ‘asio::basic_raw_socket<Protocol, Executor>::basic_raw_socket(ExecutionContext&, const endpoint_type&, typename asio::constraint<std::is_convertible<ExecutionContext&, asio::execution_context&>::value>::type) [with ExecutionContext = asio::io_context; Protocol = can::raw; Executor = asio::any_io_executor; asio::basic_raw_socket<Protocol, Executor>::endpoint_type = can::endpoint; typename asio::constraint<std::is_convertible<ExecutionContext&, asio::execution_context&>::value>::type = int]’
[build] /code/foo/main.cpp:22:75: required from here
[build] /code/foo/libs/asio/asio/include/asio/detail/reactive_socket_service.hpp:158:49: error: invalid conversion from ‘const void*’ to ‘const socket_addr_type*’ {aka ‘const sockaddr*’} [-fpermissive]
[build] 158 | socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
[build] | ~~~~~~~~~~~~~^~
[build] | |
[build] | const void*
[build] In file included from /code/foo/libs/asio/asio/include/asio/detail/socket_ops.hpp:380,
[build] from /code/foo/libs/asio/asio/include/asio/detail/socket_holder.hpp:20,
[build] from /code/foo/libs/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp:26,
[build] from /code/foo/libs/asio/asio/include/asio/detail/reactive_socket_service.hpp:31,
[build] from /code/foo/libs/asio/asio/include/asio/basic_socket.hpp:38,
[build] from /code/foo/libs/asio/asio/include/asio/basic_datagram_socket.hpp:20,
[build] from /code/foo/libs/asio/asio/include/asio.hpp:26,
[build] from /code/foo/main.cpp:8:
[build] /code/foo/libs/asio/asio/include/asio/detail/impl/socket_ops.ipp:280:49: note: initializing argument 2 of ‘int asio::detail::socket_ops::bind(asio::detail::socket_type, const socket_addr_type*, std::size_t, asio::error_code&)’
[build] 280 | int bind(socket_type s, const socket_addr_type* addr,
[build] | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~
[build] make[2]: *** [CMakeFiles/foo.dir/build.make:63: CMakeFiles/foo.dir/main.cpp.o] Error 1
[build] make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/foo.dir/all] Error 2
[build] make: *** [Makefile:106: all] Error 2
[build] Build finished with exit code 2
As the documentation states that a static_cast<>
will be performed, either the implementation or the documentation should be fixed accordingly.