ClickHouse/libs/libcommon/include/ext/shared_ptr_helper.hpp

64 lines
1.3 KiB
C++
Raw Normal View History

#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>
class shared_ptr_helper
{
protected:
2016-10-23 06:58:26 +00:00
typedef typename std::remove_const<T>::type TNoConst;
2016-10-23 07:41:26 +00:00
template <typename TAlloc>
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-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-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)...);
}
};
}