Reputation:
Here's my header file for a WebSocket client:
namespace beast = boost::beast;
namespace asio = boost::asio;
class WebSocketClient {
public:
explicit WebSocketClient(asio::io_context &ioc);
private:
using stream_type = beast::websocket::stream<beast::ssl_stream<beast::tcp_stream>>;
using ssl_context_type = asio::ssl::context;
asio::ip::tcp::resolver resolver_;
stream_type ws_;
ssl_context_type get_ssl_context();
};
And here's my definition:
WebSocketClient::WebSocketClient(asio::io_context &ioc)
: resolver_(asio::make_strand(ioc)),
ws_(asio::make_strand(ioc), get_ssl_context()) {
}
asio::ssl::context WebSocketClient::get_ssl_context() {
return WebSocketClient::ssl_context_type(asio::ssl::context_base::tlsv12_client);
}
I'm getting the error:
In template: no matching constructor for initialization of 'boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<boost::asio::execution_context &>, boost::asio::execution::detail::blocking::never_t<0>, boost::asio::execution::prefer_only<boost::asio::execution::detail::blocking::possibly_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::tracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::outstanding_work::untracked_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::fork_t<0>>, boost::asio::execution::prefer_only<boost::asio::execution::detail::relationship::continuation_t<0>>>, boost::beast::unlimited_rate_policy>>' error occurred here in instantiation of function template specialization 'boost::empty_::empty_value<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<boost::... in instantiation of function template specialization 'boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<bo... in instantiation of function template specialization 'boost::make_shared<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::executi... in instantiation of function template specialization 'boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::execution::any_executor<boost::asio::execution::context_as_t<bo... candidate constructor template not viable: expects an l-value for 2nd argument candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
I'd be very grateful if somebody could explain why I'm getting this error? If I instead use the code below, and add another private member variable ssl_context_
of type ssl_context_type
, the error goes away, but I'm not really sure why... I'm quite new to C++.
WebSocketClient::WebSocketClient(asio::io_context &ioc)
: resolver_(asio::make_strand(ioc)),
ssl_context_(asio::ssl::context_base::tlsv12_client),
ws_(asio::make_strand(ioc), ssl_context_) {
}
Upvotes: 0
Views: 1212
Reputation: 10614
The problem is that the boost::asio::ssl::stream
class constructor (and by induction, beast::websocket::stream<beast::ssl_stream<beast::tcp_stream>>
constructor) requires an l-value of boost::asio::ssl::context
as the second parameter, and WebSocketClient::get_ssl_context
returns an r-value. In other words, WebSocketClient::get_ssl_context
returns a temporary, which is not acceptable for beast::websocket::stream<beast::ssl_stream<beast::tcp_stream>>
.
ssl::context
needs to persist for the whole duration of the TLS stream, since the stream will be using the context during its operation. So the correct solution is to create an instance of ssl::context
as a data member of WebSocketClient
before ws_
and provide a reference to it to ws_
constructor.
Upvotes: 1