make_shared 不与 enable_shared_from_this 一起玩? [英] make_shared doesn't play along with enable_shared_from_this?

查看:76
本文介绍了make_shared 不与 enable_shared_from_this 一起玩?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下两个代码片段,第一个:

Consider the following two code snippets, The first one:

#include "pch.h"
#include <memory>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class tcp_connection : public std::enable_shared_from_this<tcp_connection>
{
public:
    typedef std::shared_ptr<tcp_connection> pointer;

    static pointer create(boost::asio::io_service& io_service)
    {
        return pointer(new tcp_connection(io_service));
        //second example only differs by replacing the above line with the below one
        //return std::make_shared<tcp_connection>(io_service);
    }

private:
    tcp_connection(boost::asio::io_service& io_service) //private constructor
        : socket_(io_service)
    {
    }
    tcp::socket socket_;
};

int main()
{
    return 0;
}

第二个与第一个只有一行不同,即注释行.

The second one only differs from the first with one line, that is, the commented line.

在 MSVC 2017 和 boost::asio 1.68 中,第一个版本按预期工作,而第二个版本无法编译,出现诸如不允许使用不完整类型的 tcp_async"等错误.

With MSVC 2017 and boost::asio 1.68, the first version works as intended, while the second one doesn't compile, spitting out errors such as "incomplete type is not allowed tcp_async".

我的问题是:

  1. 这是因为 std::make_shared 不能与 std:std::enable_shared_from_this 一起使用吗?
  2. 或者,这是因为 asio 关于 std::make_shared 或 std::enable_shared_from_this 如何实现的假设在 MSVC 2017 中不成立.
  3. 或者是别的什么?

推荐答案

您展示的代码中的问题源于您的类型的构造函数是私有的.

The problem in the code you show stems from the constructor of your type being private.

当您编写 new tcp_connection(io_service) 时,构造函数在 tcp_connection 本身的范围内被引用,它具有访问权限.

When you write new tcp_connection(io_service) the constructor is being referred to in the scope of tcp_connection itself, which has access.

然而,std::make_shared(或它可能使用的任何实现细节)无权访问私有构造函数,因此它无法初始化它意味着拥有共享指针的对象管理.

However, std::make_shared (or whatever implementation detail it may employ) doesn't have access to the private constructor, so it can't initialize the object it's meant to have a shared pointer manage.

如果初始化是良构的,std::make_sharedstd::enable_shared_from_this 配合得很好,但私有构造函数使它成为良构.

If the initialization is well-formed, std::make_shared works splendidly with std::enable_shared_from_this, but a private constructor makes it ill-formed.

一个常见的解决方法是使用 密钥成语.这归结为一个公共 c'tor,但它接受一个私有类型的参数.它有点像这样1:

A common workaround to this is to use the Passkey idiom. Which boils down to a public c'tor, but one that accepts a parameter of a private type. It would like somewhat like this1:

class tcp_connection2: public std::enable_shared_from_this<tcp_connection2>
{
    struct key{ explicit key(){} };
public:
    typedef std::shared_ptr<tcp_connection2> pointer;

    static pointer create(int io_service)
    {
        return std::make_shared<tcp_connection2>(io_service, key{});
    }

    tcp_connection2(int io_service, key) //private constructor, due to key
    {
    }
};

<小时>

1 - 我稍微修改了你的类定义,以便其他人更容易复制、粘贴和测试它.但同样的原则也适用于您的代码.


1 - I modified your class definition a bit, to make it easier for others to copy, paste and test this. But the same principle can be applied to your code.

这篇关于make_shared 不与 enable_shared_from_this 一起玩?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆