# Extract code that makes class shared_ptr construct-able only

I've tried using CRTP, but the forces the class to befriend CRTP Base.

template <typename T>
class SharedConstructable
: public std::enable_shared_from_this<T>
{
typedef std::shared_ptr<T> ptr_type;

public:

struct Ptr
: ptr_type
{
template<typename... Args>
Ptr(Args&&... args)
: ptr_type(new T(args...))
{
}
};
};

class SharedOnly
: SharedConstructable<SharedOnly>
{
private:
friend class SharedConstructable<SharedOnly>;
SharedOnly(int) {}
}


Usage:

SharedOnly x(5); // Error Constructor is private
SharedOnly::Ptr(5); // Correct usage;


Is there a cleaner/better way of doing this (without the friendship)?

• To do what exactly - inherit privately from SharedConstructable<T> (more or less as given) and not expose a constructor? Or was that just an attempted means to accomplish another goal? Dec 12 '13 at 3:44
• To allow construction only through shared_ptrs - It needs to inherit publicly to expose the nested Ptr class Dec 12 '13 at 5:06

If I follow you correctly, you're looking for a clean way to have a private constructor that can only be invoked by std::make_shared or std::allocate_shared. Unfortunately this does not appear to be portable or easy, and I don't see a way to avoid your request to avoid friendship. However you can make the friend something that other people cannot easily co-opt. I'd call this mildly better, but it definitely has some downsides.

As this is not portable, the scenario I'm showing here is specific to the compiler I had handy: Visual Studio 2012. First I created a class like this:

class SomeClass
{
public:
int GetValue() const { return m_val; }
// optionally provide Ptr like yours?
// static std::shared_ptr<SomeClass> Ptr(int val) { return std::make_shared<SomeClass>(val); }

private:
SomeClass(int val) { m_val = val; }
SomeClass(const SomeClass&); // = delete;
SomeClass(SomeClass&&); // = delete;
~SomeClass() {}

int m_val;
};


This is enough to prevent usage like SomeClass thing(5); Then I wanted to try to befriend std::make_shared. When I tried to compile code using this definition and std::make_shared<SomeClass>(5), I got an error pointing to what needed access:

error C2248 [...] cannot access private member [SomeClass::~SomeClass ...] while compiling class template member function 'void std::_Ref_count_obj<_Ty>::_Destroy(void)'

After befriending class std::_Ref_count_obj<SomeClass> (I first tried befriending the specific method, but that created worse problems), I also decided to fix the warning by befriending std::_Get_align<SomeClass>:

warning C4624: 'std::_Get_align<_Ty [= SomeClass]>' : destructor could not be generated because a base class destructor is inaccessible

This left me with the following additions to this class that allows std::make_shared<SomeClass>(5) but not SomeClass obj(5).

class SomeClass
{
: : :
// Allow use in VS2012 implementation of std::make_shared
friend class std::_Ref_count_obj<SomeClass>;
friend struct std::_Get_align<SomeClass>;
: : :
};


I'll leave other compilers up to you as you need them. It may be worth collecting a series of macro alternatives that you can put in any class that needs this capability.

• 1K! Congratulations! Dec 12 '13 at 21:46
• Thats an interesting approach, but unfortunately much less portable or clean... thanks for trying though Dec 13 '13 at 3:02
• @nishantjr The portability is definitely its biggest weakness. However if you hide that behind a #define BEFRIEND_MAKE_SHARED(ClassName) ... it should be easy to clean up in a single shared header. Dec 13 '13 at 15:44
• eeek, macros are evil, especially for something as trivial as this. And how is that any beeter than the original solution I gave? Dec 14 '13 at 1:35
• The use of make_shared<T>(...) is preferable to shared_ptr<T>(new T{...}) for its memory layout, and I prefer the friend statements over creating two helper classes. But as for the macro, to each his own. Dec 14 '13 at 5:51