【发布时间】: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,但基本的将分配器作为类型参数的设计没有也无法改变。