#pragma once #include namespace ext { /** Class AllocateShared allow to make std::shared_ptr from T with private constructor. * Derive your T class from shared_ptr_helper, define him as friend and call allocate_shared()/make_shared() method. */ template class shared_ptr_helper { protected: typedef typename std::remove_const::type TNoConst; template struct Deleter { void operator()(typename TAlloc::value_type * ptr) { using AllocTraits = std::allocator_traits; ptr->~TNoConst(); AllocTraits::deallocate(alloc, ptr, 1); } TAlloc alloc; }; /// see std::allocate_shared template static std::shared_ptr allocate_shared(const TAlloc & alloc, TArgs &&... args) { using AllocTraits = std::allocator_traits; TAlloc alloc_copy(alloc); auto ptr = AllocTraits::allocate(alloc_copy, 1); try { new (ptr) TNoConst(std::forward(args)...); } catch (...) { AllocTraits::deallocate(alloc_copy, ptr, 1); throw; } return std::shared_ptr( ptr, Deleter(), alloc_copy); } template static std::shared_ptr make_shared(TArgs &&... args) { return allocate_shared(std::allocator(), std::forward(args)...); } public: /// Default implementation of 'create' method just use make_shared. template static std::shared_ptr create(TArgs &&... args) { return make_shared(std::forward(args)...); } }; }