2016-08-26 21:25:05 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
namespace ext
|
|
|
|
{
|
|
|
|
|
2016-10-23 07:41:26 +00:00
|
|
|
/** Class AllocateShared allow to make std::shared_ptr<T> from T with private constructor.
|
|
|
|
* Derive your T class from shared_ptr_helper<T>, define him as friend and call allocate_shared()/make_shared() method.
|
|
|
|
*/
|
|
|
|
template <typename T>
|
2016-08-30 19:27:15 +00:00
|
|
|
class shared_ptr_helper
|
2016-08-26 21:25:05 +00:00
|
|
|
{
|
|
|
|
protected:
|
2016-10-23 06:58:26 +00:00
|
|
|
typedef typename std::remove_const<T>::type TNoConst;
|
2016-08-26 21:25:05 +00:00
|
|
|
|
2016-10-23 07:41:26 +00:00
|
|
|
template <typename TAlloc>
|
2016-08-26 21:25:05 +00:00
|
|
|
struct Deleter
|
|
|
|
{
|
2016-10-23 06:58:26 +00:00
|
|
|
void operator()(typename TAlloc::value_type * ptr)
|
|
|
|
{
|
2016-10-23 07:41:26 +00:00
|
|
|
using AllocTraits = std::allocator_traits<TAlloc>;
|
|
|
|
ptr->~TNoConst();
|
|
|
|
AllocTraits::deallocate(alloc, ptr, 1);
|
2016-10-23 06:58:26 +00:00
|
|
|
}
|
2016-10-23 07:41:26 +00:00
|
|
|
|
2016-10-23 06:58:26 +00:00
|
|
|
TAlloc alloc;
|
2016-08-26 21:25:05 +00:00
|
|
|
};
|
|
|
|
|
2016-10-23 07:41:26 +00:00
|
|
|
/// see std::allocate_shared
|
|
|
|
template <typename TAlloc, typename ... TArgs>
|
|
|
|
static std::shared_ptr<T> allocate_shared(const TAlloc & alloc, TArgs &&... args)
|
2016-10-23 06:58:26 +00:00
|
|
|
{
|
2016-10-23 07:41:26 +00:00
|
|
|
using AllocTraits = std::allocator_traits<TAlloc>;
|
2016-10-23 06:58:26 +00:00
|
|
|
TAlloc alloc_copy(alloc);
|
2016-10-23 07:41:26 +00:00
|
|
|
|
|
|
|
auto ptr = AllocTraits::allocate(alloc_copy, 1);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
new (ptr) TNoConst(std::forward<TArgs>(args)...);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
AllocTraits::deallocate(alloc_copy, ptr, 1);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::shared_ptr<TNoConst>(
|
|
|
|
ptr,
|
|
|
|
Deleter<TAlloc>(),
|
|
|
|
alloc_copy);
|
2016-10-23 06:58:26 +00:00
|
|
|
}
|
2016-08-26 21:25:05 +00:00
|
|
|
|
2016-10-23 07:41:26 +00:00
|
|
|
template <typename ... TArgs>
|
|
|
|
static std::shared_ptr<T> make_shared(TArgs &&... args)
|
2016-10-23 06:58:26 +00:00
|
|
|
{
|
|
|
|
return allocate_shared(std::allocator<TNoConst>(), std::forward<TArgs>(args)...);
|
|
|
|
}
|
2016-08-26 21:25:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|