专门用于c ++ 14中的数组类型的分配器? [英] Allocator specialized for array types in c++14?

查看:49
本文介绍了专门用于c ++ 14中的数组类型的分配器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么没有std :: allocator< T []>的数组模板专门化?在c ++ 14中?

Why isn't there an array template specialization for std::allocator<T[]> in c++14?

在尝试专门研究std :: allocator< T []>时,我自己在实现construct()和destroy()方法时遇到了死胡同.是这个原因吗?那么为什么要在std :: allocator<>中包含Construct()和destroy()部分?

When playing around trying to specialize std::allocator<T[]> myself I hit a dead-end when implementing the construct() and destroy() method. Is this the reason? Why then have construct() and destroy() part of std::allocator<>?

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.
    }
};

感谢任何提示!

推荐答案

警告:以下内容均无意义.不要在家做这个.请勿混合使用数组和动态分配.以下内容仅是拼写非常长的模板名称时的一种心理练习.

Warning: None of what follows makes sense. Don't do this at home. Don't mix arrays and dynamic allocation. The following serves merely as a mental exercise in spelling out very long template names.

标准分配器确实不提供数组构造,但是您可以轻松地构建自己的分配器.请注意,我们可以根据需要自由提供 construct()/ destroy()机制:

The standard allocator does indeed not provide for array construction, but you can easily build your own allocator that does. Note that we're free to provide construct()/destroy() mechanisms as we please:

#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 的数组.:

Here is a usage example, allocating and constructing arrays of 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 函数返回正确的内存量.

As linked in the comments, though, beware that it's impossible to prove that the inherited allocate function returns the correct amount of memory.

这篇关于专门用于c ++ 14中的数组类型的分配器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆