为什么std :: allocator< T []>没有数组模板专门化?在c ++ 14?
当试图专门化std :: allocator< T []>我自己在实现construct()和destroy()方法时遇到了死胡同。这是什么原因?为什么然后有std :: allocator<>?
的construct()和destroy()部分template <T>
class allocator <T[]> {
// ...most is similar for std::allocator<>...
template <class U, class... Args>
void construct( U *p, Args&&.. args)
{
// what to write for array construction?
// Could be std::initializer_list<T> or uniform initalizer list.
// Want to pass on to constructor somehow.
// ::new ((void *)p) [] U(std::forward<Args>(args)...);
}
template <class U>
void destroy( U* p )
{
// no-op.
}
};
感谢任何提示!
答案 0 :(得分:2)
警告:以下内容均无效。不要在家里这样做。不要混合数组和动态分配。以下仅仅是拼写很长模板名称的心理练习。
标准分配器确实不提供数组构造,但您可以轻松构建自己的分配器。请注意,我们可以随意提供construct()
/ destroy()
机制:
#include <memory>
#include <type_traits>
template <typename T>
struct array_allocator : std::allocator<T>
{
template <typename C, typename ...Args>
typename std::enable_if<std::is_array<C>::value>::type construct(C * p, Args &&... args)
{
::new (static_cast<void *>(p)) C { std::forward<Args>(args)... };
}
template <typename C, typename ...Args>
typename std::enable_if<!std::is_array<C>::value>::type construct(C * p, Args &&... args)
{
::new (static_cast<void *>(p)) C(std::forward<Args>(args)...);
}
template <typename C, typename ...Args>
typename std::enable_if<std::is_array<C>::value>::type destroy(C * p)
{
using U = typename std::remove_extent<C>::type;
using UAT = typename std::allocator_traits<array_allocator>::template rebind_traits<U>;
typename std::allocator_traits<array_allocator>::template rebind_alloc<U> ra(*this);
for (std::size_t i = 0, e = std::extent<C>::value; i != e; ++i)
{
UAT::destroy(ra, std::addressof((*p)[e - i - 1]));
}
}
template <typename C, typename ...Args>
typename std::enable_if<!std::is_array<C>::value>::type destroy(C * p)
{
p->~C();
}
};
这是一个用法示例,分配和构造13 int
。:
using T = int[13];
using TA = array_allocator<T>;
using TAT = std::allocator_traits<TA>;
#include <iostream>
int main()
{
TA a;
T * p = TAT::allocate(a, 2); // allocates space for two T's
TAT::construct(a, p, 1, 2, 3);
TAT::construct(a, p + 1, 4, 5, 6);
for (T * q = p; q != p + 2; ++q)
for (int * r = *q; r != *q + 13; ++r)
std::cout << *r << "\n";
TAT::destroy(a, p + 1);
TAT::destroy(a, p);
TAT::deallocate(a, p, 2);
}
如评论中所述,请注意,无法证明继承的allocate
函数返回正确的内存量。