user6429576
user6429576

Reputation:

No matching constructor error (Boost Beast, C++)

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

Answers (1)

Andrey Semashev
Andrey Semashev

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

Related Questions