我的问题基本上是:

How can I write a stateful allocator in C++11, given requirements on copy construction?

基本上,尽管事实上C++ 11标准现在允许有状态分配器,但我们仍然有一个要求,如果您复制某个Allocator,则该拷贝必须通过==运算符与原始比较相等。这表明该拷贝可以安全地释放由原始对象分配的内存,反之亦然。

因此,马上就已经禁止分配器维护唯一的内部状态,例如slab-allocator或内存池之类的东西。一种解决方案是对内部状态使用shared_ptr指向实现的习惯用法,以便某些原始Allocator的所有拷贝都使用相同的基础内存池。还算不错除了...

根据上面提到的问题以及可接受的答案,该标准似乎还要求Allocator<T>具有可与Allocator<U>互操作的拷贝构造函数,以便:

Allocator<T> alloc1;
Allocator<U> alloc2(alloc1);
assert(alloc1 == alloc2); // must hold true

因此,换句话说,分配器类型必须是可互操作的,而与不同的模板参数无关。这意味着,如果我使用Allocator<T>分配一些内存,那么我必须能够使用从原始Allocator<U>构造的Allocator<T>实例释放该内存。

...这几乎是阻止编写使用某种基于大小的内存池的分配器的尝试的障碍,例如simple_segregated_storage池仅基于sizeof(T)返回一定大小的块。

但是...这是真的吗?

我意识到Allocator<T>::rebind需要可互操作的拷贝构造函数,因此容器用户不需要知道诸如链表节点类型之类的内部细节。但是据我所知,standard itself似乎并没有说出那么苛刻的要求,即由Allocator<U>构造的Allocator<T>必须与原始Allocator<T>实例进行比较的要求。

该标准基本上需要以下语义,其中 X Allocator<T>类型, a1 a2 X 的实例, Y Allocator<U> b的类型Allocator<U> b,并且是Allocator<T> b的类型。

来自:§17.6.3.5 (分配器要求)
a1 == a2 returns true only if storage allocated from each can be deallocated via the other.

operator == shall be reflexive, symmetric, and transitive, and shall not exit via an exception.

a1 != a2 : same as !(a1 == a2)

a == b : same as a == Y::rebind<T>::other(b)

a != b : same as !(a == b)

X a1(a); Shall not exit via an exception. post: a1 == a

X a(b); Shall not exit via an exception. post: Y(a) == b, a == X(b)

因此,按照我的阅读方式,由Allocator<U>构造的a == b实例不一定是可互换的。该标准仅要求Y(a) == b必须等于a == b而不是,即Allocator<T>必须为true!

我认为对跨类型边界复制构造函数的要求使这一点令人困惑。但是,按照我的阅读方式,如果我有一个Allocator<U>,它必须具有一个采用boost::pool_allocator的拷贝构造函数,但这并不意味着:
Allocator<T> alloc1;
Allocator<U> alloc2(alloc1);
assert(alloc2 == alloc1);

换句话说,按照我的理解,上面的断言是允许失败的。但是我对这里的理解并不自信,因为:
  • accepted answer to this question表示相反,回答者是一个具有108K信誉的人
  • 复制构造函数要求和标准中的相等要求之间的交互有点困惑,我可能会误解这些用法。

  • 所以,我在这里正确吗? (顺便说一句,假设boost开发人员关心标准遵从性, ojit_code 的实现似乎暗示我是正确的,因为该分配器在类型边界上是不可互换的。)

    最佳答案

    您引用的最后一行:



    与您的结论相抵触。

    using X = Allocator<T>;
    using Y = Allocator<U>;
    Y b;
    X a(b);
    assert(Y(a) == b);
    assert(a == X(b));
    // therefore
    assert(a == b);
    

    关于c++ - C++ 11有状态分配器是否可以在类型边界之间互换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27471684/

    10-11 22:53