为什么Boost Variant对于boost :: beast :: websocket :: stream使用模板构造函数而不是move构造函数?

克里斯·亨特

我正在尝试将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不提供所需的openssl boost/asio/ssl.hpp

这里boost::variant应该接受T &&并使用它来实例化T内部。

这里boost::beast::websocket::stream确实有一个移动构造函数。

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未生成默认的move构造函数ssl::streamchriskohlhoff / asio#124有一个开放的问题可以使动作可构造,其中引用了boost bugtracker

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Boost beast :: websocket回调函数

Boost-Beast Websocket握手问题

Boost :: Beast Websocket双向流(C ++)

C ++中使用boost :: Beast的Websocket客户端-写入操作时引发错误

如何在Boost Beast WebSocket中传递模型类型

如何从(binary == true)boost :: beast :: websocket :: stream <tcp :: socket>读到缓冲区(boost :: beast :: flat_buffer?)中,这样它就不会转义?

使用boost :: beast的流HTTP的异步处理

使用 boost::beast 处理大型 http 响应

使用错误代码读取boost beast websocket服务器的文件结尾并且操作被取消

如何从 std::string 构造 boost::beast::http::message?

Boost :: Beast:具有websocket流水线的服务器

Boost Beast Websocket服务器异步接受失败,缓冲区溢出

带Boost :: Beast的SSL隧道

使用带有Boost Beast的lambda代替绑定

如何使用boost :: beast连续流式传输文件

使用boost :: beast解码Ntrip 1.0协议的最佳方法是什么

boost :: variant中的类holden的副本构造函数存在问题

Boost.Beast的异步读取标头

为什么std :: optional <boost :: variant <A,bool >>不能从`std :: optional <A>`成功构造?

我如何从字符串而不是文件进行Boost Beast回复

如何在构造函数而不是函数中使用boost :: hana :: unpack?

我想使用 nlohmann:json 解析带有 msgpack 数据的 boost::beast::flat_buffer

使用 Boost Beast 在 SSL 连接中构建特定于平台的客户端身份验证

如何使用boost / beast从HTTP POST请求中解析和提取有效载荷?

C ++使用Boost.asio和Beast库在体内发送数据

通过SSL(HTTPS)使用Boost-Beast(Asio)http客户端

C ++ Boost 1.66使用Beast http请求解析器解析字符串

如何使用boost :: beast,下载文件无阻塞且带有响应

为什么boost :: dynamic_bitset是模板?