C++ C++;分配器类型参数的设计模式
C++03标准库在将类型传递给要作为分配器的类时使用简单的模板类型参数。这是可能的,因为模板是如何在C++中工作的。然而,这并不十分简单,而且您可能不知道类型定义应该是什么样子——特别是在非标准类型的情况下 我认为使用适配器类instread可能是个好主意。我创建了一个示例来向您展示我的意思:C++ C++;分配器类型参数的设计模式,c++,design-patterns,stl,allocator,C++,Design Patterns,Stl,Allocator,C++03标准库在将类型传递给要作为分配器的类时使用简单的模板类型参数。这是可能的,因为模板是如何在C++中工作的。然而,这并不十分简单,而且您可能不知道类型定义应该是什么样子——特别是在非标准类型的情况下 我认为使用适配器类instread可能是个好主意。我创建了一个示例来向您展示我的意思: #ifndef HPP_ALLOCATOR_ADAPTOR_INCLUDED #define HPP_ALLOCATOR_ADAPTOR_INCLUDED #include <memory>
#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 */
#如果包含NDEF HPP分配器#适配器#
#定义包含的HPP分配器适配器
#包括
模板
结构分配器;
模板
类分配器\适配器;
模板
结构分配器
{
typedef std::分配器::常量指针常量指针;
typedef std::分配器::指针;
类型定义标准::分配器::值类型值类型;
};
模板
结构分配器
{
typedef typename std::分配器::常量指针常量指针;
typedef typename std::分配器::常量引用常量引用;
typedef typename std::分配器::差异类型差异类型;
typedef typename std::分配器::指针指针;
typedef typename std::分配器::引用;
typedef typename std::分配器::大小\类型大小\类型;
typedef typename std::分配器::值\类型值\类型;
};
模板
类分配器适配器
:公共分配器
{
公众:
模板结构重新绑定{typedef分配器_适配器其他;};
};
模板
类分配器适配器
:公共分配器
{
私人:
分配器类型m_impl;
公众:
模板结构重新绑定{typedef分配器_适配器其他;};
分配器适配器()throw()/*noexcept*/;
分配器适配器(分配器适配器常量&)throw()/*noexcept*/;
分配器适配器(分配器类型常量&)throw()/*noexcept*/;
模板分配器适配器(分配器适配器常量&)throw()/*noexcept*/;
~allocator_adaptor()throw();
指针地址(参考x)常量/*noexcept*/;
常量指针地址(常量引用x)常量/*无异常*/;
指针分配(大小\类型,分配器\特性::常量\指针提示=0);
无效解除分配(指针p,大小\类型n)/*无例外*/;
size_type max_size()常量throw()/*noexcept*/;
模板无效构造(U*p、参数类型和参数);
模板空洞破坏(U*p);
};
#endif/*包括HPP分配器适配器*/
实施应该是显而易见的。
下面是一些用法示例
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();
}
模板
int max_size(分配器类型常量和alloc)
{
//我们不知道会调用什么样的max_szie函数。
返回alloc.max_size();
}
模板
int max_size(分配器适配器常量和alloc)
{
//我们知道将调用什么样的max_size函数。
返回alloc.max_size();
}
与通常的方法相比,这是一种改进吗?在我看来不错。。。
如果你能解释一下什么时候你的设计会比通常的方式更有优势,那就太好了。举个例子对我很有帮助
“然而,这不是很好
直截了当,你可能不会
知道类型定义的确切含义
应该看起来像“
与std::分配器相比,您的实现如何改进-type definition-part,请解释实际上,您在这里的目的是引入一个基于可变参数的
构造成员,它允许您编写而不是:
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));
//...
这似乎是一个很好的功能。另一方面,移动所有初始化参数,这将禁止p+1对象的正确初始化。如果要对多个对象的相同参数重复初始化,该怎么办。我认为您当前的方法将失败(不幸的是,不是在编译时).我乍一看这样做没有什么错,但是在C++0x中使用auto
使大多数STL的使用非常简单。这个例子有问题,因为size\u type
需要不签名。我不知道你的实际意思;)转发声明与当前C++0x草案中的声明完全相同。我想你对变量模板参数很熟悉。你能给我指一下标准的段落吗?也许我真的把smth搞糊涂了。当然,你可以在C++0x草稿()
alloc::construct(p, param1, param2, param3);
alloc::construct(p+1, param1, param2, param3);