自定义分配器和 std::map

问题描述 投票:0回答:1

这是我可以使用

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

同样的问题,同样的编译器错误。

c++ memory stdmap allocator
1个回答
0
投票

您在 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。

© www.soinside.com 2019 - 2024. All rights reserved.