Allocator专门用于c ++ 14中的数组类型?

时间:2014-07-02 23:25:07

标签: c++ templates template-specialization c++14 allocator

为什么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.
    }
};

感谢任何提示!

1 个答案:

答案 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函数返回正确的内存量。