没有匹配的构造函数来初始化我的自定义分配器
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
。
我写了一个自定义分配器。但是,当我将 list.sort()
添加到 main()
.
虽然代码有点长,但这是最小的可行代码段:
#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
。