gpt4 book ai didi

c++ - 为什么 Boost Variant 使用模板构造函数而不是 boost::beast::websocket::stream 的移动构造函数?

转载 作者:行者123 更新时间:2023-11-30 04:58:41 27 4
gpt4 key购买 nike

我正在尝试包装 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] ) websockets 相同。我陷入了编译失败。

我能想到的最简单的失败示例是:

#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 .

根据 here , boost::variant应该接受 T &&并用它来实例化 T内部。

根据 here , boost::beast::websocket::stream确实有一个移动构造函数。

移动构造函数更具体,那么为什么编译器选择可变参数构造函数 (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&&) 的描述中:

If NextLayer is move constructible, this function will move-construct a new stream from the existing stream.

事实证明,boost::asio::ssl::stream 是不可移动构造的,因此未生成stream 的默认移动构造函数。有一个 Unresolved 问题使 ssl::stream 在引用 chriskohlhoff/asio#124boost bugtracker 中移动可构造。

该问题的解决方案是使用 ssl::stream 的可移动构造实现,就像 Beast 示例 here 中提供的那样,它看起来可能在 处可用boost/beast/experimental/core/ssl_stream.hpp 在更高版本的 Beast 中(不在 1.67.0 中)。

关于c++ - 为什么 Boost Variant 使用模板构造函数而不是 boost::beast::websocket::stream 的移动构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51585147/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com