I have this code that doesn\'t work, but I think the intent is clear:
testmakeshared.cpp
#include
class A {
public:
stat
The root of the problem is that if the function or class you friend makes lower level calls to your constructor, they have to be friended too. std::make_shared isn't the function that's actually calling your constructor so friending it makes no difference.
class A;
typedef std::shared_ptr APtr;
class A
{
template
friend class std::_Ref_count_obj;
public:
APtr create()
{
return std::make_shared();
}
private:
A()
{}
};
std::_Ref_count_obj is actually calling your constructor, so it needs to be a friend. Since that's a bit obscure, I use a macro
#define SHARED_PTR_DECL(T) \
class T; \
typedef std::shared_ptr ##T##Ptr;
#define FRIEND_STD_MAKE_SHARED \
template \
friend class std::_Ref_count_obj;
Then your class declaration looks fairly simple. You can make a single macro for declaring the ptr and the class if you prefer.
SHARED_PTR_DECL(B);
class B
{
FRIEND_STD_MAKE_SHARED
public:
BPtr create()
{
return std::make_shared();
}
private:
B()
{}
};
This is actually an important issue. To make maintainable, portable code you need to hide as much of the implementation as possible.
typedef std::shared_ptr APtr;
hides how you're handling your smart pointer a bit, you have to be sure to use your typedef. But if you always have to create one using make_shared, it defeats the purpose.
The above example forces code using your class to use your smart pointer constructor, which means that if you switch to a new flavor of smart pointer, you change your class declaration and you have a decent chance of being finished. DO NOT assume your next boss or project will use stl, boost etc. plan for changing it someday.
Doing this for almost 30 years, I've paid a big price in time, pain and side effects to repair this when it was done wrong years ago.