Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
352 views
in Technique[技术] by (71.8m points)

c++ - Why is there no std::allocate_unique function in C++14?

Why does shared_ptr have allocate_shared while unique_ptr does not have allocate_unique?
I would like to make a unique_ptr using my own allocator: do I have to allocate the buffer myself and then assign it to a unique_ptr?
This seems like an obvious idiom.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

do I have to allocate the buffer myself and then assign it to a unique_ptr?

Not just a buffer, a pointer to an object. But the object might need to be destroyed by the allocator, and the memory definitely needs to deallocated by the allocator, so you also need to pass the allocator the the unique_ptr. It doesn't know how to use an allocator, so you need to wrap it in a custom deleter, and that becomes part of the unique_ptr's type.

I think a generic solution would look something like this:

#include <memory>

template<typename Alloc>
struct alloc_deleter
{
  alloc_deleter(const Alloc& a) : a(a) { }

  typedef typename std::allocator_traits<Alloc>::pointer pointer;

  void operator()(pointer p) const
  {
    Alloc aa(a);
    std::allocator_traits<Alloc>::destroy(aa, std::addressof(*p));
    std::allocator_traits<Alloc>::deallocate(aa, p, 1);
  }

private:
  Alloc a;
};

template<typename T, typename Alloc, typename... Args>
auto
allocate_unique(const Alloc& alloc, Args&&... args)
{
  using AT = std::allocator_traits<Alloc>;
  static_assert(std::is_same<typename AT::value_type, std::remove_cv_t<T>>{}(),
                "Allocator has the wrong value_type");

  Alloc a(alloc);
  auto p = AT::allocate(a, 1);
  try {
    AT::construct(a, std::addressof(*p), std::forward<Args>(args)...);
    using D = alloc_deleter<Alloc>;
    return std::unique_ptr<T, D>(p, D(a));
  }
  catch (...)
  {
    AT::deallocate(a, p, 1);
    throw;
  }
}

int main()
{
  std::allocator<int> a;
  auto p = allocate_unique<int>(a, 0);
  return *p;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...