无法使用包含不同下一层的两个 ssl_stream 来编译代码

Can't compile code with two ssl_stream that wrap different next layers

我想了解为什么在为 tcp 层创建两个 ssl_streams 包装不同的对象时,会出现以下编译错误:

------ Build started: Project: test, Configuration: Debug x64 ------
>Microsoft (R) C/C++ Optimizing Compiler Version 19.22.27905 for x64
>Copyright (C) Microsoft Corporation.  All rights reserved.
>cl /c /I"D:\workspace\openssl-static\openssl-OpenSSL_1_1_1a\openssl-OpenSSL_1_1_1a\include" /ID:\workspace\boost\VS19\boost_1_70_0 /Zi /W3 /WX- /diagnostics:column /Od /Ob0 /D WIN32 /D _WINDOWS /D _WIN32_WINNT=0x0600 /D _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING /D "CMAKE_INTDIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /std:c++17 /Fo"test.dir\Debug\" /Fd"test.dir\Debug\vc142.pdb" /Gd /TP /errorReport:prompt D:\workspace\main.cpp
>main.cpp
>D:\workspace\boost\VS19\boost_1_70_0\boost/beast/ssl/ssl_stream.hpp(655,5): error C2995:  'void boost::beast::teardown(boost::beast::role_type,boost::beast::ssl_stream<NextLayer> &,boost::system::error_code &)': function template has already been defined
>D:\workspace\boost\VS19\boost_1_70_0\boost/beast/ssl/ssl_stream.hpp(655): message :  see declaration of 'boost::beast::teardown'
>D:\workspace\main.cpp(12): message :  see reference to class template instantiation 'boost::beast::ssl_stream<boost::asio::ip::tcp::socket>' being compiled
>D:\workspace\boost\VS19\boost_1_70_0\boost/beast/ssl/ssl_stream.hpp(668,5): error C2995:  'void boost::beast::async_teardown(boost::beast::role_type,boost::beast::ssl_stream<NextLayer> &,TeardownHandler &&)': function template has already been defined
>D:\workspace\boost\VS19\boost_1_70_0\boost/beast/ssl/ssl_stream.hpp(668): message :  see declaration of 'boost::beast::async_teardown'
>Done building project "test.vcxproj" -- FAILED.

如果两个流具有相同的模板参数(即,两者都具有 boost::beast::tcp_streamboost::asio::ip::tcp::socket)。

#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/beast/core/tcp_stream.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>

int main() {
  boost::asio::io_context ioc;
  boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client);
  ctx.set_default_verify_paths();
  boost::beast::ssl_stream<boost::beast::tcp_stream> stream_1(ioc, ctx);
  boost::beast::ssl_stream<boost::asio::ip::tcp::socket> stream_2(ioc, ctx);
}

我想了解这是错误还是预期的行为。如果是第二个,如果有人向我解释原因,那就太好了。另外,我想更好地了解在什么情况下值得使用 tcp_stream,以及在什么情况下使用套接字。

我认为这是 Beast 中的一个 bug/QOI 问题。它声明模板友元函数 在 class 声明中,即 teardown.

但是模板友元不依赖于所有 class 模板模板参数,因此 ssl_stream<> 与其他模板参数的下一个实例定义相同的模板友元函数。

简单的解决方法是使定义超出-class 和朋友 仅在 class 正文中声明。

所以,它变成了:

template<class NextLayer>
class ssl_stream
    : public net::ssl::stream_base
{
    // ... many lines snipped ...

    #if ! BOOST_BEAST_DOXYGEN
    template<class SyncStream>
    friend
    void
    teardown(
        boost::beast::role_type role,
        ssl_stream<SyncStream>& stream,
        boost::system::error_code& ec);

    template<class AsyncStream, class TeardownHandler>
    friend
    void
    async_teardown(
        boost::beast::role_type role,
        ssl_stream<AsyncStream>& stream,
        TeardownHandler&& handler);
    #endif
};

template<class SyncStream>
static inline void
teardown(
    boost::beast::role_type role,
    ssl_stream<SyncStream>& stream,
    boost::system::error_code& ec)
{
    // Just forward it to the underlying ssl::stream
    using boost::beast::websocket::teardown;
    teardown(role, *stream.p_, ec);
}

template<class AsyncStream, class TeardownHandler>
static inline void
async_teardown(
    boost::beast::role_type role,
    ssl_stream<AsyncStream>& stream,
    TeardownHandler&& handler)
{
    // Just forward it to the underlying ssl::stream
    using boost::beast::websocket::async_teardown;
    async_teardown(role, *stream.p_,
        std::forward<TeardownHandler>(handler));
}

I've opened an issue + pull request for that

I was going to open a pull request but it appears that the identical fix (yay) already landed on develop in 1de60a046292dcd42bb0097176e0139ba4ad051b which is in master and tagged for boost-1.71.0 and boost-1.71.0.beta1