Reputation: 21
I want to enforce shared_ptr
for a few classes. I'm using a static
factory function to encapsulating private constructors:
#include <memory>
class MyClass
{
public:
static std::shared_ptr<MyClass> create() {
auto a = std::shared_ptr<MyClass>(new MyClass());
return a;
}
private:
MyClass();
~MyClass();
}
}
This template fails with C2440
, (function-style cast) in VS2017
, but works fine in VS2015
and I have no idea why. A make_shared-version works fine in both but requires public constructors.
Any idea which option I'm missing?
Upvotes: 1
Views: 697
Reputation: 8228
In addition to other answers: if you don't want to declare std::shared_ptr
as a friend of your class and you don't want to make your destructor public, you can create a shared_ptr
with the custom deleter. For that you will need some method from your MyClass
that can access the private destructor and call delete
. For example:
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();
You can also declare destroy
method as non-static and commit a suicide inside (one of a few situations when it actually makes sense).
Upvotes: 1
Reputation: 44258
Looks like VS2017 complains about accessing destructor from std::shared_ptr
, so you may want to declare std::shared_ptr
as friend of MyClass. For std::make_shared
you can use a trick from this answer 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() {}
};
Upvotes: 2