【问题标题】:In allocator-aware STL classes, why are the allocators not template template arguments?在分配器感知的 STL 类中,为什么分配器不是模板模板参数?
【发布时间】:2014-10-23 16:48:08
【问题描述】:

STL 中所有可识别分配器的类模板都必须使用分配器类型进行实例化。如果分配器不是 template 参数而是 template template 参数,对用户来说不是更方便吗?

为了演示,std::vector 和 std::basic_string 类模板分别具有以下签名:

template<class T, class Allocator = std::allocator<T>> class vector;
template<class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>> class basic_string;

如果我有自定义分配器:

template <typename T>
class MyAllocator
{
    // ...
};

并且想要实例化一个字符串向量,该向量使用我的自定义分配器为向量和字符串的内部字符数组分配内部存储,事情很快变得尴尬:

typedef std::vector<std::basic_string<char, std::char_traits<char>, MyAllocator<char> >, MyAllocator<std::basic_string<char, std::char_traits<char>, MyAllocator<char>>>> CustomAllocStringVector;

使用额外的 typedef,可以稍微简化一下:

typedef std::basic_string<char, std::char_traits<char>, MyAllocator<char>> CustomAllocString;
typedef std::vector<CustomAllocString, MyAllocator<CustomAllocString>> CustomAllocStringVector;

但困扰我的是,为什么要强制用户显式指定分配器的完整类型?如果我将分配器用于 char 的向量,难道不应该说分配器的类型为分配器char >? p>

如果 std::vector 和 std::basic_string 的签名是:

template<typename T, template <typename ElementType> class AllocatorType = std::allocator> class vector;
template<typename CharT, typename Traits = std::char_traits<CharT>, template <typename ElementType> class AllocatorType = std::allocator> class basic_string;

与上面相同的向量类型可以更简单地定义为:

typedef std::basic_string<char, std::char_traits<char>, MyAllocator> CustomAllocString;
typedef std::vector<CustomAllocString, MyAllocator> CustomAllocStringVector;

当然,我的方式是要求所有分配器都是模板,但是任何应该至少可重用的分配器类都必须满足这个要求吗?

我确信这是有充分理由的,但目前我没有看到。

【问题讨论】:

  • 其实,就在我输入这个问题的时候,我又想到了一件事。为什么分配器必须关心它用于什么类型?为什么客户端代码不能只要求 x 字节对齐 y 而不提及任何类型名称?这样,整个问题就会消失。
  • 如果您希望分配器的类型在容器中包含的类型的补充(或替代)上被模板化怎么办?
  • 分配器的类型不必是类模板的特化。您可以将其限制为单一类型,这对于特殊用途的分配器可能很有用。
  • 这是一个相关问题(实际上几乎是重复的)Why is allocator::rebind necessary when we have template template parameters
  • @dyp 他们添加了allocator_traits,但基本的将分配器作为类型参数的设计没有也无法改变。

标签: c++ c++11 allocator


【解决方案1】:

这将引入一个要求,即分配器类型是一个类模板,只有一个模板参数,专用于容器的value_type。你的提议将消除

template<typename T, unsigned int PoolNumber = 0>
class my_allocator;

作为一个有效的分配器。

同时,我可以简单地将typedef 用于我的分配器类型,无需拆开或重复其模板名称:

template<typename T> class my_allocator;

typedef my_allocator<int> int_allocator;

std::list<int, int_allocator> ...    // valid currently, difficult to express with your proposal

【讨论】:

  • template&lt;class T&gt;using pool_3_allocator=my_allocator&lt;T, 3&gt;;template&lt;unsigned pool&gt;struct pool_helper{template&lt;class T&gt;using allocator=my_allocator&lt;T, pool&gt;;}; 处理这种极端情况需要多花些功夫。我怀疑分配器接口真的很旧并且无法更改这一事实更为重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 2012-09-03
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多