为什么Boost Variant使用模板构造函数而不是Boost::beast::websocket::stream的移
Why does Boost Variant use the template constructor instead of the move constructor for boost::beast::websocket::stream?
我正在尝试将boost::beast::websocket::stream<T>
(针对2个特定的T
(封装在boost::variant
中,以允许对TLS([T = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>]
(和非TLS([T = boost::asio::ip::tcp::socket]
(websocket进行相同的处理。我陷入了编译失败的困境。
我能想出的最简单的失败例子是:
#include <boost/asio/ssl.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/variant.hpp>
using tcp = boost::asio::ip::tcp;
namespace ws = boost::beast::websocket;
namespace ssl = boost::asio::ssl;
using base_ws = boost::variant<
ws::stream<tcp::socket>, ws::stream<ssl::stream<tcp::socket>>>;
class test
{
public:
static void init( tcp::socket && socket )
{
ssl::context ctx{ ssl::context::tlsv12_server };
ws::stream<ssl::stream<tcp::socket>> s{ std::move( socket ), ctx };
base_ws{ std::move( s ) };
}
};
int main()
{}
编译失败,出现错误:
In file included from /server/src/ws_server.cpp:9:
In file included from /include/boost/beast/websocket.hpp:18:
In file included from /include/boost/beast/websocket/stream.hpp:3455:
/include/boost/beast/websocket/impl/stream.ipp:47:7: error: no matching constructor for initialization of 'boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >'
: stream_(std::forward<Args>(args)...)
^ ~~~~~~~~~~~~~~~~~~~~~~~~
/include/boost/variant/detail/initializer.hpp:122:27: note: in instantiation of function template specialization 'boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > >::stream<boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > >' requested here
new(dest) value_T( boost::detail::variant::move(operand) );
^
/include/boost/variant/variant.hpp:1687:28: note: in instantiation of member function 'boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::make_initializer_node::apply<boost::mpl::pair<boost::detail::variant::initializer_root, mpl_::int_<0> >, boost::mpl::l_iter<boost::mpl::list2<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > > > >::initializer_node, mpl_::int_<1> >, boost::mpl::l_iter<boost::mpl::list1<boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > > > >::initializer_node::initialize' requested here
initializer::initialize(
^
/include/boost/variant/variant.hpp:1858:9: note: in instantiation of function template specialization 'boost::variant<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > >::convert_construct<boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > >' requested here
convert_construct( detail::variant::move(operand), 1L);
^
/server/src/ws_server.cpp:372:20: note: in instantiation of function template specialization 'boost::variant<boost::beast::websocket::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >, boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > >::variant<boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > > >' requested here
return base_ws( std::move( s ) );
^
/include/boost/asio/ssl/stream.hpp:64:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> > >' to 'const boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp> >' for 1st argument
class stream :
^
/include/boost/asio/ssl/stream.hpp:98:3: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
stream(Arg&& arg, context& ctx)
^
我会提供godbolt,但它超时了,而且coliru没有提供boost/asio/ssl.hpp
所需的openssl。
根据这里,boost::variant
应该接受T &&
,并使用它在内部实例化T
。
根据这里,boost::beast::websocket::stream
确实有一个move构造函数。
move构造函数更具体,那么编译器为什么选择第一个注释中所示的可变构造函数(stream<...>
(呢?
boost::beast::websocket::stream<
boost::asio::ssl::stream<
boost::asio::basic_stream_socket<boost::asio::ip::tcp>
>
>::stream<
boost::beast::websocket::stream<
boost::asio::ssl::stream<
boost::asio::basic_stream_socket<boost::asio::ip::tcp>
>
>
>
我使用的是Boost 1.66.0和Clang 7。
我忽略的关键信息是在boost::beast::websocket::stream::stream(stream&&)
:的描述中
如果
NextLayer
是可移动构造的,则此函数将从现有流中移动构造一个新流。
原来boost::asio::ssl::stream
是不可移动的,所以没有生成stream
的默认移动构造函数。在引用boost错误跟踪器的chriskohlhoff/asio#124中,使ssl::stream
移动可构建是一个悬而未决的问题。
因此,问题的解决方案是使用ssl::stream
的可移动构造实现,如此处Beast示例中提供的实现,看起来它可能在Beast的更高版本(而不是1.67.0(中的boost/beast/experimental/core/ssl_stream.hpp
中可用
高级服务器flex示例显示了如何使用处理SSL和纯websocket会话的代码构建服务器,而无需使用变体:https://github.com/boostorg/beast/blob/c2ecba968c06a22a61c67b8887f5b477bb32a99a/example/advanced/server-flex/advanced_server_flex.cpp#L227
- 如何在boost beast http请求中设置http头
- 带有 Boost.Beast 的异步读取标头
- 如何使用 boost beast websocket 客户端收听 websocket feed?
- Boost (Beast) websocket:同步写入挂起
- 如何使用boost/beast从HTTP POST请求中解析和提取有效负载?
- Boost Beast 异步服务器失败,断言失败:(id_ != T::id) 在多个 aync 调用中
- boost beast Websocket Multi Request Server/Client 并不是真正的 mul
- "Body requirements not met"将 req 传递给 c++ 中的方法(Boost Beast 库)
- Websocket 客户端在 C++ 中使用 boost::Beast - 在写入操作时抛出错误
- 断开连接后重新连接boost beast(asio)websocket和http连接时出错
- 为什么Boost Variant使用模板构造函数而不是Boost::beast::websocket::stream的移
- boost beast websocket服务器也接受http连接
- 我可以使用 Boost.Asio 和 Boost.Beast 库发出 HTTPS 请求或 HTTP/2 请求吗?
- Boost::Beast Websocket Bidirection Stream (C++)
- 如何在 Boost::Beast 上继续使用 websocket?
- Cmake忽略了我所有关于在boost::beast存储库中在哪里找到提升的指令
- Boost-Beast 异步 Web 套接字 服务器-客户端异步读写 不在控制台上写入输出
- boost :: Beast Sync http客户端的超时
- 使用带有SSL(HTTPS)的Boost-Beast(ASIO)HTTP客户端
- 通过boost::beast设计具有不同订阅费率的多个订阅