根据 http://en.cppreference.com/w/cpp/concept/Allocator ,一个可以用作分配器类型的类必须满足许多要求。但是,我找不到 C++ 标准指定的相同要求。该标准只要求分配器类型不能是非类类型。 (参见 n3797 20.7.8.1)
如果我有一个空类 Alloc
和一个完全特化的std::allocator_traits<Alloc>
, 我可以使用 Alloc
如下:
#include <vector>
struct Alloc {};
template<>
std::allocator_traits<Alloc>
{
// full of definitions as per the requirements for std::allocator_traits<T>
};
int main()
{
std::vector<int, Alloc> coll;
coll.push_back(8);
}
最佳答案
只要您打算将分配器与 STL 容器(或遵循相同约定的代码)一起使用,您就可以通过专门为您的类定义 std::allocator_traits
来定义您的分配器(然后只需定义它就足够了; 考虑到这一点,我认为您甚至可能为此目的劫持现有的非分配器类),因为不会直接调用您的分配器,而是通过 std::allocator_traits
特化。
但是,这样做似乎违背了该类模板的目的,因为通过定义该规范,您将失去模板已设置的所有默认值,因此您必须重新定义所有内容,这并不比在你的Alloc
直接上课。具体来说,17.6.4.2.1 似乎使其成为未定义的行为,仅专门化单个成员函数,如 std::allocator_traits<Alloc>::allocate
,当然必须对其进行定义。
预期用途显然是根本不专门化 std::allocator_traits
,而只是定义没有提供默认值的 Alloc
成员(本质上是 value_type
、 allocate
和 deallocate
;在末尾17.6.3.5 有一个示例结构 SimpleAllocator
提供了一个最小的工作接口(interface)),或者您想要覆盖默认值( std::allocator_traits
设置为使用任何定义的成员优先于其默认值)。
作为个人问题,我建议通常总是将 typedefs propagate_on_container_move_assignment
和 propagate_on_container_swap
(但不是他们的 copy_assignment
亲戚)从默认状态 false_type
覆盖为 true_type
。由于容器类模板不允许非等效分配器实例与现有内存相关联(这最终会导致它被错误地释放),因此它们必须准备好放弃移动语义并重新分配所有内容,以防(相关的)两个提到的类型是 false_type
和 分配器实例被发现是不相等的。编译器可能足够聪明,可以检测到您的(无状态)分配器类型实例永远不会比较不相等,并将上述“准备好”的复杂情况视为死代码。然而,如果该类型是 true_type
,这种死代码处理更容易检测并且更确定发生,然后还将申请有状态分配器(允许传播)。换句话说,我认为这两个默认值只是选择错误。
关于c++ - 只要 std::allocator_traits<T> 是专门的,我可以使用任何类 T 作为分配器类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24567133/