2

我目前正在寻找扩展任意标准符合分配器类型的最佳方法。明确一点:我不想编写自定义分配器。我只想将特定的扩展或行为“添加”到已经存在的扩展或行为。我已经创建了一个示例,它的外观如何。请注意,以下代码仅用于说明目的。

#ifndef HPP_SMART_ALLOCATOR_INCLUDED
#define HPP_SMART_ALLOCATOR_INCLUDED


#include <memory>
#include <map>


template<typename T>
struct allocator_traits;

template<typename T, class allocator_type = std::allocator<T>>
class smart_allocator;


template<>
struct allocator_traits<void>
{
    typedef std::allocator<void>::const_pointer const_pointer;
    typedef std::allocator<void>::pointer       pointer;
    typedef std::allocator<void>::value_type    value_type;
};

template<typename T>
struct allocator_traits
{
    typedef typename std::allocator<T>::const_pointer   const_pointer;
    typedef typename std::allocator<T>::const_reference const_reference;
    typedef typename std::allocator<T>::difference_type difference_type;
    typedef typename std::allocator<T>::pointer         pointer;
    typedef typename std::allocator<T>::reference       reference;
    typedef typename std::allocator<T>::size_type       size_type;
    typedef typename std::allocator<T>::value_type      value_type;
};


template<class allocator_type>
class smart_allocator<void, allocator_type>
    : public allocator_traits<void>
{
public:
    template<typename U> struct rebind { typedef smart_allocator<U, typename allocator_type::rebind<U>::other> other; };
};

template<typename T, class allocator_type>
class smart_allocator
    : public  allocator_traits<T>,
      private allocator_type
{
public:
    using typename allocator_traits<T>::const_pointer;
    using typename allocator_traits<T>::const_reference;
    using typename allocator_traits<T>::difference_type;
    using typename allocator_traits<T>::pointer;
    using typename allocator_traits<T>::reference;
    using typename allocator_traits<T>::size_type;
    using typename allocator_traits<T>::value_type;
    template<typename U> struct rebind { typedef smart_allocator<U, typename allocator_type::rebind<U>::other> other; };

    smart_allocator() throw() /*noexcept*/;
    smart_allocator(allocator_type const&) throw() /*noexcept*/;
    virtual ~smart_allocator() throw();

    virtual ~smart_allocator()
    {
        std::map<pointer, size_type>::iterator i = this->m_map.begin();
        while (i != this->m_map.end())
        {
            this->allocator_type::deallocate(i->first, i->second);
            ++i;
        }
    }

    pointer allocate(size_type n, allocator_traits<void>::const_pointer hint = 0)
    {
        pointer p = this->allocator_type::allocate(n, hint);
        this->m_map.insert(std::pair<pointer, size_type>(p, n));
        return p;
    }

    void deallocate(pointer p, size_type n) /*noexcept*/
    {
        std::map<pointer, size_type>::iterator iter = this->m_map.find(p);
        if (iter != this->m_map.end())
            this->allocator_type::deallocate(iter->first, iter->second);
    }

    using allocator_type::address;
    using allocator_type::construct;
    using allocator_type::destroy;
    using allocator_type::max_size;

private:
    smart_allocator(smart_allocator const&) throw();
    smart_allocator& operator=(smart_allocator const&);

    std::map<pointer, size_type> m_map;
};


#endif /* HPP_SMART_ALLOCATOR_INCLUDED */

请考虑以下注意事项:

  • 模板参数 allocator_type 可以是任何标准符合类型。它不限于 std::allocator。这是所有 STL 实现都使用的相同技术。
  • 从 allocator_type 派生时,我们需要使用私有继承,因为 std::allocator 成员函数都不是虚拟的。然而, std::allocator& alloc = smart_allocator() 不会做你所期望的。

你认为这适用吗?

4

2 回答 2

1

您当然需要实现一个复制构造函数和复制赋值运算符,否则当容器按值传递分配器时,您的映射可能会被破坏(特别是您可能会导致双重删除)。可能还有其他我没有注意到的考虑因素。

于 2011-06-13T18:56:23.720 回答
1

立即想到的是装饰器;正如参考资料所述,“装饰器可用于使对象适应新情况而无需重写原始对象的代码。” 如果我理解您的问题,这听起来像是您所追求的。

于 2011-06-13T19:24:15.417 回答