首页 > 解决方案 > 使用精美的指针实现自定义分配器

问题描述

我正在尝试实现我自己的分配器,它应该与 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 似乎没有保存我花哨的指针,而是原始指针。

标签: c++memory-managementallocator

解决方案


在深入研究了这个问题之后,我想由于libstdc++内部限制,这根本是不可能的。这是一个已知的旧错误,“基于节点的容器内部不使用分配器的指针类型”

容器节点通过内置指针链接在一起,但它们应该使用分配器的指针类型。目前我认为只有std::vector这样做是正确的。...

它应该与 Clang 和 libc++(使用-stdlib=libc++命令行选项)一起使用,并进行了一些修复:

  1. FancyPtr<void>::pointer_to(...)应该是一个有效的成员函数。现在不是,因为void&不存在。
  2. FancyPtr应该提供operator!=(...)成员函数。

需要这些修复以使您的代码至少可编译。它是否能正常工作超出了这个答案的范围。


推荐阅读