c++ 类标准::__cxx11::列表〈标准::对〈整数,整数>,标准::列表分配器〈标准::对〈整数,整数>没有名为“front”的成员

tez616oj  于 2023-02-17  发布在  其他
关注(0)|答案(1)|浏览(111)

我尝试在Kubuntu 20操作系统上使用gcc-12将我的代码从C11标准升级到C20。我有一个自定义分配器:

namespace allocators {
template <class T,int n = 16384>
class ListAllocator : public std::allocator<T> {
public:
    typedef typename std::allocator<T>::size_type size_type;
    typedef typename std::allocator<T>::pointer pointer;
public:
    ListAllocator() : allocator<T>()                             {}
    ListAllocator(const ListAllocator<T,n>& a) : std::allocator<T>(a) {}
    ListAllocator(const allocator<T>& a) : std::allocator<T>(a)       {}

    char* _Charalloc(size_type N) {
        if (idx==0)
           return allocator<T>::_Charalloc(N);
        else
            return reinterpret_cast<char*>(arena[--idx]);
    }

    void deallocate(void* p, size_type s) {
        if (idx == n)
            allocator<T>::deallocate(p,s);
        else
            arena[idx++] = p;
    }

    static void deallocate() {
        while(idx) 
            ((allocator<T>*)0)->deallocate( reinterpret_cast<typename std::allocator<T>::pointer>(arena[--idx]) , size_type(sizeof(T)) );
    }

    static void*    arena[n];
    static size_t   idx;          // index of 1st emty field in arena
};

template <class T,int n>  void*  ListAllocator<T,n>::arena[n];
template <class T,int n>  size_t ListAllocator<T,n>::idx;

}

我有一个结构体,包含以下内容:

typedef T                           Coord;

  typedef std::pair<Coord , Coord >   Point;
  typedef ListAllocator<Point> ListPointAllocator;

  typedef std::list<Point2d,ListPointAllocator >   Pl;
  Pl*  plPtr;
  Point & edgeRef() { return beg ? plPtr->front() : plPtr->back();}

我得到错误:class std::__cxx11::list<std::pair<int, int>, std::ListAllocator<std::pair<int, int>, 16384> >'} has no member named 'front' class std::__cxx11::list<std::pair<int, int>, std::ListAllocator<std::pair<int, int>, 16384> >'} has no member named 'back'
我想找个解释,但什么也没找到。到底是什么问题呢?

yacmzcpb

yacmzcpb1#

您的分配器不满足Allocator要求。
如果不这样做,那么将其用作标准库模板的分配器会有未定义的行为,编译失败是比较幸运的结果之一。
一些问题:
1.您的分配器是从一个具有非类型模板参数的模板示例化的。因此没有提供默认的rebind<U>成员模板,您需要自己提供它。请注意,自C20起,std::allocator不再提供rebind。在C20之前,您的分配器确实从它继承了rebind,但它会重新绑定到std::allocator<U>,这是错误的。技术上是UB,并且可能导致您的自定义分配函数实际上没有被使用。不要从std::allocator继承,这是不必要的。Allocator 所需的大多数功能都是通过std::allocator_traits默认的。因此,最小的 Allocator 只需要提供构造函数value_typeallocatedeallocateoperator==(在C++20之前还有operator!=)。在您的情况下,rebind也是必需的,正如我上面解释的。

  1. _Charalloc是全局保留标识符,因为它以下划线开头,后跟大写字母。您不能使用它。分配器应改为定义allocate成员函数,类似于std::allocator::allocate
  2. allocator<T>::_Charalloc是标准库的一个实现细节。你不应该使用它。如果你想引用底层分配器的分配,使用std::allocator_traits<std::allocator<T>>::allocate或直接使用::operator new
    1.您的分配器不会检查各个分配的大小是否相同。无法保证allocate不会以不同的大小作为参数被调用。此外,在重新绑定之后,可能会对不同的类型进行不同的对齐。因此,您也不能在不检查对齐要求的情况下重用旧的分配。
    1.您需要template<typename U> ListAllocator(const ListAllocator<U,n>&);的构造函数。

相关问题