【问题标题】:Can I use any class T as an allocator type as long as std::allocator_traits<T> is specialized?只要 std::allocator_traits<T> 是专门的,我可以使用任何类 T 作为分配器类型吗?
【发布时间】:2014-07-04 05:16:54
【问题描述】:

根据http://en.cppreference.com/w/cpp/concept/Allocator,一个可以用作分配器类型的类必须满足许多要求。但是,我找不到 C++ 标准规定的相同要求。标准只要求分配器类型不能是非类类型。 (见 n3797 20.7.8.1)

如果我有一个空类Alloc 和一个完全专业化的std::allocator_traits&lt;Alloc&gt;,我可以使用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);
}

【问题讨论】:

  • 你可以做到(大多数情况下;你仍然需要提供operator == 等),但我看不出你从中获得了什么,因为你必须重新实现专业化而不是依赖默认值。

标签: c++ memory-management standards typetraits allocator


【解决方案1】:

只要您打算将分配器与 STL 容器(或遵循相同约定的代码)一起使用,您就可以通过专门为您的类指定 std::allocator_traits 来定义您的分配器(然后定义它就足够了; 考虑到这一点,我认为您甚至可能为此目的劫持现有的非分配器类),因为不会直接调用您的分配器,而是通过 std::allocator_traits 专业化。

这样做似乎违背了该类模板的目的,因为通过定义该规范,您将失去模板已设置的所有默认值,因此您必须重新定义所有内容,这并不比在你的Alloc 直接上课。具体来说,17.6.4.2.1 似乎使得只专门化个别成员函数(如 std::allocator_traits&lt;Alloc&gt;::allocate)成为未定义行为,当然必须对其进行定义。

显然,其预期用途是完全不专门化std::allocator_traits,而只是定义那些没有提供默认值的Alloc 成员(基本上是value_typeallocatedeallocate;在末尾17.6.3.5 有一个示例结构 SimpleAllocator,它提供了一个最小的工作接口),或者您想要覆盖默认值(std::allocator_traits 设置为使用任何已定义的成员,优先于其默认值)。

作为个人问题,我建议通常始终将 typedef propagate_on_container_move_assignmentpropagate_on_container_swap(但不是它们的 copy_assignment 相对)从默认的 false_type 状态覆盖到 true_type。由于容器类模板不能允许非等效分配器实例与现有内存相关联(这最终会导致它被错误地释放),因此它们必须准备放弃移动语义并重新分配所有内容以防万一(相关之一)提到的两种类型是false_type 分配器实例被发现是不相等的。可能是编译器足够聪明,可以检测到您的(无状态)分配器类型实例从不比较不相等,并将上述“准备好”的并发症视为死代码。但是,如果该类型为true_type,则这种死代码处理更容易检测并且更确定会发生,然后也将应用于有状态分配器(允许传播)。换句话说,我认为这两个默认设置是错误的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    相关资源
    最近更新 更多