【问题标题】:C++ Design Pattern for allocator type arguments分配器类型参数的 C++ 设计模式
【发布时间】:2011-06-13 18:55:25
【问题描述】:

C++03 标准库在将类型传递给作为分配器的类时使用简单的模板类型参数。这是可能的,因为模板在 C++ 中的工作方式。但是,它不是很简单,您可能不知道类型定义到底应该是什么样子 - 尤其是在非标准类型的情况下。

我认为使用适配器类 instread 可能是个好主意。我创建了一个示例来向您展示我的意思:

#ifndef HPP_ALLOCATOR_ADAPTOR_INCLUDED
#define HPP_ALLOCATOR_ADAPTOR_INCLUDED


#include <memory>


template<typename T>
struct allocator_traits;

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


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 allocator_adaptor<void, allocator_type>
    : public allocator_traits<void>
{
public:
    template<typename U> struct rebind { typedef allocator_adaptor<U, allocator_type> other; };
};

template<typename T, class allocator_type>
class allocator_adaptor
    : public allocator_traits<T>
{
private:
    allocator_type m_impl;

public:
    template<typename U> struct rebind { typedef allocator_adaptor<U, allocator_type> other; };

    allocator_adaptor() throw() /*noexcept*/;
    allocator_adaptor(allocator_adaptor const&) throw() /*noexcept*/;
    allocator_adaptor(allocator_type const&) throw() /*noexcept*/;
    template<typename U> allocator_adaptor(allocator_adaptor<U, allocator_type> const&) throw() /*noexcept*/;
    ~allocator_adaptor() throw();

    pointer       address(reference x) const /*noexcept*/;
    const_pointer address(const_reference x) const /*noexcept*/;

    pointer   allocate  (size_type, allocator_traits<void>::const_pointer hint = 0);
    void      deallocate(pointer p, size_type n) /*noexcept*/;
    size_type max_size  () const throw() /*noexcept*/;

    template<class U, typename... argument_types> void construct(U* p, argument_types&&... args);
    template<class U> void destroy(U* p);
};


#endif /* HPP_ALLOCATOR_ADAPTOR_INCLUDED */

实现应该是显而易见的。 这是一些用法示例。

template<class allocator_type>
int max_size(allocator_type const& alloc)
{
    // we don't know what kind of max_szie function will be called.
    return alloc.max_size();
}

template<typename T>
int max_size(allocator_adaptor<T> const& alloc)
{
    // we know what kind of max_size function will be called.
    return alloc.max_size();
}

与通常的方式相比,这是一种改进吗?

【问题讨论】:

  • 我第一眼看不出这样做有什么问题,但是在 C++0x 中使用 auto 使得大多数 STL 的使用非常简单。
  • 这个例子是有问题的,因为size_type必须是未签名的。

标签: c++ design-patterns stl allocator


【解决方案1】:

实际上你的意思是引入一个construct 成员,它基于可变参数并允许你写而不是:

typedef std::allocator<T> my_alloc;
my_alloc alloc;
my_alloc::pointer p = alloc.allocate(10);
alloc::construct(p, T(param1, param2, param3));
alloc::construct(p+1, T(param1, param2, param3));
//...

一些更简单的形式:

alloc::construct(p, param1, param2, param3);
alloc::construct(p+1, param1, param2, param3);

这似乎是一个不错的功能。另一方面,您移动了所有初始化参数,这将禁止 p+1 对象的正确初始化。如果我想为多个对象重复初始化相同的参数怎么办。我认为您当前的方法会失败(不幸的是不会在编译时)。

【讨论】:

  • 我不知道您的实际意思;) 前向声明与当前 C++0x 草案中的完全一样。我认为您对可变参数模板参数感到困惑。
  • 您能指出解释它的标准段落吗?可能是我真的很困惑。
  • 当然,您可以在 C++0x 草案 (open-std.org/jtc1/sc22/WG21/docs/papers/2011/n3242.pdf) 中的 14.5.3 Variadic templates 找到它
【解决方案2】:

我觉得不错... 最好能解释一下您的设计何时会在通常的方式上具有优势。一个例子对我很有帮助

“但是,它不是很 直截了当,你可能不会 知道类型定义到底是什么 应该看起来像“

与 std::allocator 相比,您的实现如何改进 -type 定义部分,请解释一下

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 2013-07-14
    • 1970-01-01
    • 2016-05-12
    • 2014-07-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多