c++ - 使用精美的指针实现自定义分配器
问题描述
我正在尝试实现我自己的分配器,它应该与 STL 容器一起使用并使用自定义的花式指针实现。
我很确定,我的类满足所有要求(根据 cppreference),但我的实现不能为 std::list 编译,因为没有从我的花哨指针到普通指针的转换。
一个显示问题的最小示例,(但显然不是我真正的实现):
花式_ptr.h:
#include <cstddef>
template<typename T>
class FancyPtr {
T *ptr;
FancyPtr(T *ptr, bool) : ptr(ptr) {}; //Bool to be non standart
public:
using element_type = T;
FancyPtr(std::nullptr_t n) : FancyPtr() {};
template<class S>
operator FancyPtr<S>() {
return {ptr};
}
T &operator*() { return *ptr; }
T &operator[](size_t n) { return ptr[n]; }
T *operator->() { return ptr; }
bool operator==(const FancyPtr &other) { return ptr == other.ptr; };
static FancyPtr pointer_to(element_type &r) { return FancyPtr(&r, false); };
};
TrivialAllocator.h:
#include "fancy_ptr.h"
template<typename T>
class TrivialAllocator {
public:
using pointer = FancyPtr<T>;
using value_type = T;
TrivialAllocator() = default;
template<typename Other>
TrivialAllocator(const TrivialAllocator<Other> &other) {};
template<typename Other>
TrivialAllocator(TrivialAllocator<Other> &&other) {};
TrivialAllocator(TrivialAllocator &alloc) = default;
pointer allocate(size_t n) { return pointer::pointer_to(*new T[n]); }
void deallocate(pointer ptr, size_t n) { delete[] &*ptr; };
bool operator==(const TrivialAllocator &rhs) const { return true; };
bool operator!=(const TrivialAllocator &rhs) const { return false; };
};
主.cpp:
#include "TrivialAllocator.h"
#include <list>
int main() {
struct Test {};
using AllocT = std::allocator_traits<TrivialAllocator<long double>>;
static_assert(std::is_same_v<FancyPtr<long double>,std::pointer_traits<AllocT::pointer>::pointer>);
static_assert(std::is_same_v<FancyPtr<Test>, std::pointer_traits<AllocT::pointer>::rebind<Test>>);
std::list<long double, AllocT::allocator_type> list;
}
静态断言没问题。
谁能告诉我我必须做什么才能让这个工作?
PS:我知道 operator-> 类似于转换运算符,但根本问题是 std::list 似乎没有保存我花哨的指针,而是原始指针。
解决方案
在深入研究了这个问题之后,我想由于libstdc++
内部限制,这根本是不可能的。这是一个已知的旧错误,“基于节点的容器内部不使用分配器的指针类型”:
容器节点通过内置指针链接在一起,但它们应该使用分配器的指针类型。目前我认为只有
std::vector
这样做是正确的。...
它应该与 Clang 和 libc++(使用-stdlib=libc++
命令行选项)一起使用,并进行了一些修复:
FancyPtr<void>::pointer_to(...)
应该是一个有效的成员函数。现在不是,因为void&
不存在。FancyPtr
应该提供operator!=(...)
成员函数。
需要这些修复以使您的代码至少可编译。它是否能正常工作超出了这个答案的范围。
推荐阅读
- elasticsearch - 如何在 Elasticsearch 中获取匹配的文本位置?
- php - 我如何订购两张桌子?
- dji-sdk - 时间线任务中的 DJIGimbalAttitudeAction
- angularjs - 如何在ionic v1中调用cordova插件
- python - Html中的字符串格式
- reactjs - 如何在给定api的情况下进行简单的发布请求
- parsing - 将字符串与值一起拆分为相似的元素
- python-3.x - 如何将社交注册/登录与 Auth0 与 AWS Lambda 与 Python 集成?
- php - Yii 1.16 ORM findAll()
- javascript - 为什么轮值不同?