这是我可以使用
gcc
编译的代码:
#include <iostream>
#include <map>
template <class T>
class map_alloc {
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U>
struct rebind {
typedef map_alloc<U> other;
};
pointer allocate(size_type n, const void* hint = 0) {
T* t = (T*) malloc ( n * sizeof(T) );
return t;
}
void deallocate(pointer p, size_type n) {
free ( p );
}
};
typedef map_alloc<std::map<int, int>::value_type> alloctor;
int main() {
std::map<int, int, std::less<int>, alloctor> dummy;
(void)(dummy);
return 0;
}
但是尝试使用
MSVC
进行编译失败,并出现相当奇怪的错误(见下文)。
测试:
g++
(Ubuntu 11.4.0-1ubuntu1~22.04)
11.4.0
msvc 2022 community, toolset v143
。
有什么想法吗?
std::map
上 MSVC
的自定义内存分配器的任何示例?
谢谢你。
Build started at 1:02...
1>------ Build started: Project: malloc_tester, Configuration: Debug x64 ------
1>alloc_tester.cpp
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: 'static_cast': cannot convert from 'map_alloc<U>' to 'map_alloc<U>'
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: with
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: [
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: ]
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: and
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: [
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: U=std::_Container_proxy
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27): error C2440: ]
1>(compiling source file 'alloc_tester.cpp')
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1>'map_alloc<U>::map_alloc': no overloaded function could convert all the argument types
1> with
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Temp\ConsoleApplication4\malloc_tester\alloc_tester.cpp(29,1):
1> could be 'map_alloc<U>::map_alloc(map_alloc<U> &&)'
1> with
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> 'map_alloc<U>::map_alloc(map_alloc<U> &&)': cannot convert argument 1 from 'map_alloc<U>' to 'map_alloc<U> &&'
1> with
1> [
1> U=std::_Container_proxy
1> ]
1> and
1> [
1> U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1> ]
1> and
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> Reason: cannot convert from 'map_alloc<U>' to 'map_alloc<U>'
1> with
1> [
1> U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1> ]
1> and
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> C:\Temp\ConsoleApplication4\malloc_tester\alloc_tester.cpp(29,1):
1> or 'map_alloc<U>::map_alloc(const map_alloc<U> &)'
1> with
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> 'map_alloc<U>::map_alloc(const map_alloc<U> &)': cannot convert argument 1 from 'map_alloc<U>' to 'const map_alloc<U> &'
1> with
1> [
1> U=std::_Container_proxy
1> ]
1> and
1> [
1> U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1> ]
1> and
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> Reason: cannot convert from 'map_alloc<U>' to 'const map_alloc<U>'
1> with
1> [
1> U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1> ]
1> and
1> [
1> U=std::_Container_proxy
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1> while trying to match the argument list '(map_alloc<U>)'
1> with
1> [
1> U=std::_Tree_node<std::pair<const int,int>,std::_Default_allocator_traits<std::allocator<std::pair<const int,int>>>::void_pointer>
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,27):
1>the template instantiation context (the oldest one first) is
1> C:\Temp\ConsoleApplication4\malloc_tester\alloc_tester.cpp(34,50):
1> see reference to class template instantiation 'std::map<int,int,std::less<int>,alloctor>' being compiled
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\map(72,20):
1> see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled
1> with
1> [
1> _Kty=int,
1> _Ty=int,
1> _Pr=std::less<int>,
1> _Alloc=alloctor
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1071,6):
1> while compiling class template member function 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::~_Tree(void) noexcept'
1> with
1> [
1> _Kty=int,
1> _Ty=int,
1> _Pr=std::less<int>,
1> _Alloc=alloctor
1> ]
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\map(369,1):
1> see the first reference to 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::~_Tree' in 'std::map<int,int,std::less<int>,alloctor>::~map'
1> with
1> [
1> _Kty=int,
1> _Ty=int,
1> _Pr=std::less<int>,
1> _Alloc=alloctor
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1075,25): error C2530: '_Alproxy': references must be initialized
1>(compiling source file 'alloc_tester.cpp')
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1076,32): error C3536: '_Alproxy': cannot be used before it is initialized
1>(compiling source file 'alloc_tester.cpp')
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1076,9): error C2672: '_Delete_plain_internal': no matching overloaded function found
1>(compiling source file 'alloc_tester.cpp')
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xmemory(1135,19):
1>could be 'void std::_Delete_plain_internal(_Alloc &,_Alloc::value_type *const ) noexcept'
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1076,9):
1> Failed to specialize function template 'void std::_Delete_plain_internal(_Alloc &,_Alloc::value_type *const ) noexcept'
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1076,9):
1> With the following template arguments:
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtree(1076,9):
1> '_Alloc=int'
1>Done building project "malloc_tester.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 1:02 and took 00,554 seconds ==========
在不同版本的
MSVC
上进行了测试。我在网上找不到操作示例。
我在这里找到了一个例子:https://github.com/moya-lang/Allocator/tree/master
同样的问题,同样的编译器错误。
您在 MSVC 中遇到的问题与自定义分配器中的重新绑定结构有关。 MSVC对标准库的实现似乎比GCC的实现更加严格。
要解决此问题,您可以修改重新绑定结构以继承 std::allocator_traits::rebind_alloc,而不是定义新的 map_alloc 类型。这是更新后的代码:
#include <iostream>
#include <map>
template <class T>
class map_alloc {
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U>
struct rebind {
typedef typename std::allocator_traits<map_alloc<T>>::template rebind_alloc<U> other;
};
pointer allocate(size_type n, const void* hint = 0) {
T* t = (T*) malloc ( n * sizeof(T) );
return t;
}
void deallocate(pointer p, size_type n) {
free ( p );
}
};
typedef map_alloc<std::pair<const int, int>> allocator_type;
int main() {
std::map<int, int, std::less<int>, allocator_type> dummy;
(void)(dummy);
return 0;
}
此修改应该可以解决 MSVC 上的编译错误。请注意,为了清楚起见,我还将分配器类型的 typedef 简化为 allocator_type。