没有匹配的构造函数来初始化我的自定义分配器

No matching constructor for initialization of my custom allocator

我写了一个自定义分配器。但是,当我将 list.sort() 添加到 main().

时,Clang/LLVM 编译器开始抱怨我的分配器初始化构造函数不匹配

虽然代码有点长,但这是最小的可行代码段:

#include <iostream>
#include <ctime>
#include <list>
#include <limits>

template<typename T, int start = 16, int ratio = 2, int thrsh = 65536>
class Allocator
{
private:
    T  *avsp;
    int used, vcnt;
    struct _block
    {   struct _block *next;
        T nodes[1];
    } *pool, *pblock;

public :
    //    typedefs
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

public :
    // convert an allocator<T> to allocator<U>
    template<typename U>
    struct rebind
    {
        typedef Allocator<U, start, ratio, thrsh> other;
    };

public :
    explicit Allocator()
    {
        avsp = NULL;
        used = 0;
        vcnt = 0;
        pool = NULL;
        pblock = NULL;
    }

    ~Allocator() {}
    explicit Allocator(Allocator const&) {}

    template<typename U>
    explicit Allocator(Allocator<U, start, ratio, thrsh> const&) {}

    // address
    pointer address(reference r)
    {
        return &r;
    }
    const_pointer address(const_reference r)
    {
        return &r;
    }

    // memory allocation
    pointer allocate(size_type cnt = 1,  // SHOULD ALWAYS BE ONE
                     typename std::allocator<void>::const_pointer = 0)
    {
        (void)cnt;

        if (avsp == NULL)
        {
            if (vcnt == 0)
            {
                pblock = pool;
                pool   = NULL;

                if (used == 0)
                    vcnt = (used = start);
                else
                    vcnt = (used < thrsh) ? (used *= ratio) : (used = thrsh);

                if (pool != NULL)
                    std::cerr << "Potential Memory Leak." << std::endl;  // Compatibility Purpose Only

                pool = static_cast<struct _block*>(malloc((sizeof(*pblock)) +
                (sizeof(pblock->nodes)) * (size_t)(used - 1)));

                if (pool == NULL)
                    std::cerr << "Memory Allocation Failure." << std::endl;  // Compatibility Purpose Only

                pool->next = pblock;
            }

            return &(pool->nodes[--vcnt]);
        }
        else
        {
            // NOT IMPL: AVSP
            exit(EXIT_FAILURE);
        }

        // NEVER REACH !!
        exit(EXIT_FAILURE);
    }
    void deallocate(pointer p, size_type)
    {
        // NOT IMPL: AVSP
        (void)p;
    }

    // size
    size_type max_size() const
    {
        return std::numeric_limits<size_type>::max() / sizeof(T);
    }

    // construction/destruction
    void construct(pointer p, const T& t)
    {
        new(p) T(t);
    }
    void destroy(pointer p)
    {
        p->~T();
    }

    template<typename U>
    bool operator==(const Allocator<U, start, ratio, thrsh>&) const
    {
        return true;
    }

    template<typename U>
    bool operator!=(const Allocator<U, start, ratio, thrsh>&) const
    {
        return false;
    }
};

int main (void)
{
    std::list<uint32_t, Allocator<uint32_t>> list;

    for (int cnt = 0; cnt < 1 << 27; cnt++)
        list.push_back(rand());

    list.sort();  // <-- Problems Here

    return 0;
}

这是错误信息:

/usr/include/c++/4.6/bits/move.h:127
error: no matching constructor for initialization of 'Allocator<std::_List_node<unsigned int>, 16, 2, 65536>'
/usr/include/c++/4.6/bits/allocator.h:163:4:
in instantiation of function template specialization 'std::swap<Allocator<std::_List_node<unsigned int>, 16, 2, 65536> >' requested here
/usr/include/c++/4.6/bits/stl_list.h:1185:4:
in instantiation of member function 'std::__alloc_swap<Allocator<std::_List_node<unsigned int>, 16, 2, 65536>, false>::_S_do_it' requested here
/usr/include/c++/4.6/bits/list.tcc:375:11:
in instantiation of member function 'std::list<unsigned int, Allocator<unsigned int, 16, 2, 65536> >::swap' requested here
<this-file>.cpp:??:10:
in instantiation of member function 'std::list<unsigned int, Allocator<unsigned int, 16, 2, 65536> >::sort' requested here

只需简单地删除 explicit,一切都会如愿以偿。

具有 explicit 复制构造函数的类型不满足 CopyConstructible 要求,分配器必须是 CopyConstructible。 https://wg21.link/lwg2081

澄清了这一点

因此您需要从复制构造函数中删除 explicit。为了安全(并确保所有标准库实现的可移植性),您可能还应该从转换构造函数模板中删除 explicit