I am working on a version of std::unique_ptr and std::make_unique for aligned memory. The purpose of this is vectorization, e.g., SSE or AVX, which has higher alignment requirements than the underlying types.My header providing aligned::unique_ptr and aligned::make_unique (compiles with C++11, no need for C++14 support):#ifndef ALIGNED_H#define ALIGNED_H#include <algorithm>#include <memory>// The make_unique parts are copied from GCC (/usr/include/c++/4.9/bits), and// were adapted for alignment.namespace aligned {/// For internal use only!namespace details {/// Deleter for single object in aligned memory, used by aligned::unique_ptrtemplate <class T> struct Deleter {  void operator()(T *data) const {    // Single object, was created by placement-new => destruct explicitly    data->~T();    // Data allocated by posix_memalign, so we must free it.    free(data);  }};/// Specialization of Deleter for array of objects, used by aligned::unique_ptrtemplate <class T> struct Deleter<T[]> {  void operator()(T *data) const {    // Data allocated by posix_memalign, so we must free it.    free(data);  }};/// Allocation function for aligned memory, used by aligned::make_uniquetemplate <typename T, std::size_t alignment>inline typename std::remove_extent<T>::type *alloc(std::size_t num) {  // Ensure minimum alignment for given type  std::size_t align = std::max(std::alignment_of<T>::value, alignment);  // If T is an array type, we remove the []  using TYPE = typename std::remove_extent<T>::type;  TYPE *mem = 0;  int error = posix_memalign((void **)&mem, align, sizeof(TYPE) * num);  if (error == EINVAL)    throw std::logic_error(Error: Alignment must be a power of two                            (posix_memalign returned EINVAL));  else if (error != 0)    throw std::bad_alloc();  return mem;}/// Default alignment is set to 64 Byte, i.e., the most common cache-line size./// This alignment is sufficient at the least for AVX-512.constexpr std::size_t default_alignment = 64;} // namespace details/// Typedef providing aligned::unique_ptrtemplate <class T> using unique_ptr = std::unique_ptr<T, details::Deleter<T>>;/// For internal use only!namespace details {template <typename T> struct MakeUniq { typedef unique_ptr<T> single_object; };template <typename T> struct MakeUniq<T[]> { typedef unique_ptr<T[]> array; };template <typename T, std::size_t Bound> struct MakeUniq<T[Bound]> {  struct invalid_type {};};} // namespace details/// aligned::make_unique for single objectstemplate <typename T, std::size_t alignment = details::default_alignment,          typename... Args>inline typename details::MakeUniq<T>::single_objectmake_unique(Args &&... args) {  // Placement-new into aligned memory  // We use constructor with {} to prevent narrowing  return unique_ptr<T>(new (details::alloc<T, alignment>(1))                           T{std::forward<Args>(args)...});}/// aligned::make_unique for arrays of unknown boundtemplate <typename T, std::size_t alignment = details::default_alignment>inline typename details::MakeUniq<T>::array make_unique(std::size_t num) {  // We are not using new, which would prevent allocation of  // non-default-constructible types, so we need to verify explicitly  static_assert(std::is_default_constructible<                    typename std::remove_extent<T>::type>::value,                Error: aligned::make_unique<T[]> supports only                 default-constructible types);  static_assert(std::is_pod<                    typename std::remove_extent<T>::type>::value,                Error: aligned::make_unique<T[]> supports only                 pod types);  return unique_ptr<T>(details::alloc<T, alignment>(num));}/// Disable aligned::make_unique for arrays of known boundtemplate <typename T, typename... Args>inline typename details::MakeUniq<T>::invalid_typemake_unique(Args &&...) = delete;} // namespace aligned#endif // ALIGNED_HBased on that we can allocate aligned memory (in this example I use the default alignment of 64 bytes instead of specifying it explicitly as a second template argument):#include aligned.hstruct Foo {  Foo(int x, int y) : x(x), y(y){};  int x;  int y;};int main() {  // Single object  auto x = aligned::make_unique<double>(16.0);  // Forbidden thanks to {} --- did the user want to write  // aligned::make_unique<double[]>(16)?  // auto x = aligned::make_unique<double>(16);  auto foo = aligned::make_unique<Foo>(3, 4);  // Array  auto y = aligned::make_unique<double[]>(16);  // Disabled for arrays of known bounds:  // auto y = aligned::make_unique<double[16]>(16);  // Forbidden --- there is no default constructor:  // auto foo = aligned::make_unique<Foo[]>(16);  // Forbidden --- calling constructor & destructors on each array element is  // not implemented:  // auto s = aligned::make_unique<std::string[]>(16);}Is there any flaw or problem in my solution?As @T.C. pointed out in a comment on Stack Overflow (where I had previously posted this question) there is a problem when allocating an array of, e.g., std::string, because constructors and destructors must be called in that case. Therefore I currently disabled make_unique<T[]> for non-POD types, but I would also appreciate a generic solution for that.
Implementation of unique_ptr and make_unique for aligned memory
c++;c++11;pointers
Looks reasonable to me. Good use of standard components to build the thing you want!TYPE *mem = 0;int error = posix_memalign((void **)&mem, align, sizeof(TYPE) * num);I'd have writtenvoid *mem = nullptr;int error = posix_memalign(&mem, align, sizeof(TYPE) * num);to get rid of the ugly casts and 0-as-null. (Then return static_cast<TYPE*>(mem).)template <class T> using unique_ptr = std::unique_ptr<T, details::Deleter<T>>;I have to keep in mind while reading your code that unique_ptr<T> and std::unique_ptr<T> are different types (despite being spelled the same). That's a good design choice for the user of your library, but it's a terrible design choice for the reader of your library. Therefore, IMO you should create a new name for your type in this file, e.g. details::uniq_ptr; and then at the very end of the file you should introduce template<class T> using unique_ptr = details::uniq_ptr<T>;. That way you get the best of both worlds: the user gets two things with the same name, and the library reader gets distinct names for distinct concepts.For make_unique<T[]>, you'll have to return an aligned::unique_ptr<T[]>, which must remember the size of the array (or else retrieve it from something like malloc_usable_size or _msize, but those are problematic because they're analogous to vector::capacity instead of vector::size. You don't want to destroy more items than the user provided). Fortunately you can partially specialize your unique_ptr template so that unique_ptr<T[]> has that extra size member. (The STL's unique_ptr is also specialized for T[], but doesn't keep that explicit size member because operator delete[] doesn't need it. Instead, it's specialized to provide a different set of accessor operators: [] instead of * and so on.)// We use constructor with {} to prevent narrowing// Forbidden thanks to {} --- did the user want to write// aligned::make_unique<double[]>(16)?// auto x = aligned::make_unique<double>(16);This is a breaking change / deliberate asymmetry compared to std::unique_ptr<T>. What's wrong with narrowing? Your example implies that you're worried someone might accidentally leave the [] off an array type, but that's pretty far-fetched, isn't it?