我在 codereview 上也问过同样的问题,但他们善意地指出,这个问题更适合 SO。
考虑以下代码:
#include<vector>
#include<memory>
template<typename T>
struct S final {
struct B {
virtual void push_back(T&& v) = 0;
virtual ~B() { }
};
template<class Allocator>
struct D final: public B {
D(Allocator alloc): vec{alloc} { }
void push_back(T&& v) override { vec.push_back(v); }
std::vector<T, Allocator> vec;
};
S(): S{std::allocator<T>{}} { }
template<class Allocator>
S(Allocator alloc): ptr{new D<Allocator>{alloc}} { }
~S() { delete ptr; }
void push_back(T&& v) { ptr->push_back(std::move(v)); }
B* ptr;
};
int main() {
int x = 42;
S<int> s1{};
S<double> s2{std::allocator<double>{}};
s1.push_back(42);
s2.push_back(x);
}
这是一个用于解决问题的最小示例。
这个想法是类型删除接受自定义分配器(在本例中为std::vector
)的东西,以便改变容器的定义(即将分配器的类型作为其类型的一部分)类似于 std::function
的类型(不将分配器的类型作为其类型的一部分,但仍然接受分配器施工期间)。
上面的代码可以编译,但我对这个类是否能按预期工作这一事实表示怀疑。
换句话说,每当该类的用户提供自己的分配器时,它都会用作新的 std::vector
的参数,其类型会被删除,但不会用于分配ptr
指向的 D
实例。
这是一个有效/合乎逻辑的设计吗?或者分配器应该对每次分配保持一致? 我的意思是,这是否也可以在 STL 或其他一些主要库中找到,或者它没有多大意义?
最佳答案
没有正确的答案,设计是合理的,但使用用户提供的分配器来创建派生对象也是合理的。为此,您需要在类型删除的上下文中进行销毁和释放,以便可以使用分配器:
template<typename T>
struct S final {
struct B {
// ...
virtual void destroy() = 0;
protected:
virtual ~B() { }
};
template<class Allocator>
struct D final: public B {
// ...
void destroy() override {
using A2 = std::allocator_traits<Allocator>::rebind_alloc<D>;
A2 a{vec.get_allocator()};
this->~D();
a2.deallocate(this, 1);
}
};
S(): S{std::allocator<T>{}} { }
template<class Allocator>
S(Allocator alloc): ptr{nullptr} {
using DA = D<Allocator>;
using AT = std::allocator_traits<Allocator>;
static_assert(std::is_same<typename AT::pointer, typename AT::value_type*>::value, "Allocator doesn't use fancy pointers");
using A2 = AT::rebind_alloc<DA>;
A2 a2{alloc};
auto p = a2.allocate(1);
try {
ptr = ::new((void*)p) DA{alloc};
} catch (...) {
a2.deallocate(p);
throw;
}
}
~S() { ptr->destroy(); }
// ...
};
(此代码断言 Allocator::pointer
是 Allocator::value_type*
,为了支持分配器,如果情况不正确,则需要使用 pointer_traits
在指针类型之间进行转换,这留给读者作为练习。)
关于c++ - 类型删除和分配器 : what's the expected behavior?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36028562/