typename 为模板化基类时的模板类定义

问题描述 投票:0回答:1

我正在实现一个可以使用 tcp 和 unix 套接字的简单服务器后端。
这是监听器块:

static asio::awaitable<void> listener() {
    const auto executor = co_await asio::this_coro::executor;
    asio::local::stream_protocol::acceptor acceptor(executor, asio::local::stream_protocol::endpoint(socket_file_));

    for (;;) {
        auto socket = co_await acceptor.async_accept(asio::use_awaitable);
        ...

之后,会话将通过使用此

Session
创建
socket
类的实例来初始化。

在这种情况下,

socket
的类型为
asio::local::stream_protocol::socket
,但在 tcp 情况下,类型将为
asio::ip::tcp::socket
.
他们都有一个基类 -
asio::basic_stream_socket
我想实现通用
Session
类:

template <typename Protocol, typename Executor>
class Session : public std::enable_shared_from_this<Session<Protocol, Executor>> {
    using Socket = asio::basic_stream_socket<Protocol, Executor>;

public:
    explicit Session(Socket sock) : socket_(std::move(sock)) {}

    void start() {
        ...

在这种实现中,我必须在

Protocol
方法中明确指定类型
Executor
listener

    std::make_shared<Session<asio::local::stream_protocol, asio::any_io_executor>>(std::move(socket))->start();

    std::make_shared<Session<decltype(socket)::protocol_type, decltype(socket)::executor_type>>(std::move(socket))->start();

看起来很麻烦,看起来很多余。

有没有办法优化

Session
类模板定义?

c++ templates boost-asio c++20
1个回答
0
投票

作为免责声明,我对使用 boost asio 的异步会话一无所知。但是如果我正确理解你的问题,你想简化

shared_ptr
s 到你的
Session
类的创建,而不必写出复杂的模板参数。

一般来说,您可以使用模板化的自由工厂函数

create_session
来实现这一点,它可以从传递的参数中推断出它的模板参数,如下所示:

#include <memory>

//********************** my very own boost asio implementation **********************//

template <typename Protocol, typename Executor>
struct asio_basic_stream_socket{
    using protocol_type = Protocol;
    using executor_type = Executor;
};

template <typename Protocol, typename Executor>
struct asio_local_stream_protocol_socket : asio_basic_stream_socket<Protocol, Executor> {};

template <typename Protocol, typename Executor>
struct asio_ip_tcp_socket : asio_basic_stream_socket<Protocol, Executor> {};

//********************** Session **********************//

template <typename Protocol, typename Executor>
class Session //: std::enable_shared_from_this<Session> 
{
public:
    using Socket = asio_basic_stream_socket<Protocol, Executor>;

    template <typename S>
    friend auto create_session(S);
private:
    Session(Socket){}
};

template <typename Socket>
auto create_session(Socket s)
{
    using P = typename Socket::protocol_type;
    using E = typename Socket::executor_type;
    using S = Session<P,E>;
    return std::shared_ptr<S>(new S(std::move(s)));
}

//********************** Usage **********************//

int main()
{
    asio_local_stream_protocol_socket<int, bool> x;
    auto session_ptr_x = create_session(x);

    asio_ip_tcp_socket<std::string, double> y;
    auto session_ptr_y = create_session(x);
}

一些注意事项:

  • create_session
    的正文中还有一些模板混乱,但这被很好地隐藏起来了。
  • 至少为了这个最小的例子,
    Session
    不需要从
    std::enable_shared_from_this
    派生。
  • 例子中,
    Session
    的构造函数是private的。这是基于
    Session
    实例只会通过工厂函数创建的假设。这当然不是必需的。

https://godbolt.org/z/15MhPTrWK

© www.soinside.com 2019 - 2024. All rights reserved.