std :: shared_ptr模板因C2440失败

时间:2018-07-24 12:50:17

标签: c++ shared-ptr

我想对几个班级实施shared_ptr。我正在使用static工厂函数来封装私有构造函数:

#include <memory>

class MyClass
{
    public:

    static std::shared_ptr<MyClass> create() {
        auto a = std::shared_ptr<MyClass>(new MyClass());
        return a;
    }

    private:
        MyClass();
        ~MyClass();
    }
}

此模板在VS2017中以C2440(函数样式转换)失败,但在VS2015中工作正常,我也不知道为什么。 make_shared-version在这两种版本中都可以正常工作,但需要公共构造函数。

知道我缺少哪个选项吗?

2 个答案:

答案 0 :(得分:2)

好像VS2017抱怨从std::shared_ptr访问析构函数,因此您可能想将std::shared_ptr声明为MyClass的朋友。对于std::make_shared,您可以使用此答案How do I call ::std::make_shared on a class with only protected or private constructors?

中的技巧
class MyClass
{
public:

    static std::shared_ptr<MyClass> create() {
        struct make_shared_enabler : MyClass {};
        return std::make_shared<make_shared_enabler>();
    }

    // compiles fine for gcc without friend though
    //friend class std::shared_ptr<MyClass>;
private:
   MyClass() {}
   ~MyClass() {}
};

live example

答案 1 :(得分:1)

除了其他答案:如果您不想将std::shared_ptr声明为班级的朋友,并且不想将析构函数公开,则可以使用以下方法创建shared_ptr自定义删除器。为此,您将需要MyClass中的某些方法可以访问私有析构函数并调用delete。例如:

class MyClass
{
public:
    static std::shared_ptr<MyClass> create() {
        auto a = std::shared_ptr<MyClass>(new MyClass(),
            [](MyClass* ptr) { destroy(ptr); });
        return a;
    }
    static void destroy(MyClass* ptr) { delete ptr; }
    private:
        MyClass(){}
        ~MyClass(){}
};

// later in the source code
    auto ptr = MyClass::create();

您还可以将destroy方法声明为非静态方法,并在内部自杀(这种情况实际上是有实际意义的几种情况之一)。