2017-02-20 79 views
1

我写了一个自定义分配器。然而,当我将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 

回答

0

explicit复制构造函数的类型不符合CopyConstructible要求,并且分配器必须是CopyConstructible。这是明确的https://wg21.link/lwg2081

所以你需要从您的副本构造函数中删除explicit。为了安全(并确保所有标准库实现的可移植性),您应该也可以从转换构造函数模板中删除explicit

+0

感谢您的进一步解释。 –

2

只是简单地删除explicit,一切工作就像一个魅力。

相关问题