如何在C++20中为std::map编写自定义分配器

rbpvctlc  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(225)

正如我从cppreference中了解到的,我们需要为自己的自定义分配器定义rebind_alloc。但我并不真正理解如何让我自己的分配器对我的Map节点也有效。
我做了什么:

  1. template <class T>
  2. class Allocator2
  3. {
  4. public:
  5. using value_type = T;
  6. using size_type = std::size_t;
  7. using difference_type = std::ptrdiff_t ;
  8. using propagate_on_container_move_assignment = std::true_type;
  9. // no idea what I need for rebind_alloc here... ???
  10. template<typename U>
  11. using rebind_alloc = typename std::allocator_traits<Allocator2<T>>::template rebind_alloc<U>;
  12. T* allocate(size_type n, const void* hint = 0)
  13. {
  14. std::cout << "Alloc" << n << std::endl;
  15. return static_cast<T*>(malloc(n*sizeof(T)));
  16. }
  17. void deallocate(T* p, size_type n) { free( p); }
  18. size_type max_size() const { return size_type(std::numeric_limits<unsigned int>::max() / sizeof(T)); }
  19. void construct(T* p, const T& value) { _construct(p, value); }
  20. void destroy(T* p) { _destroy(p); }
  21. };
  22. template<class T, class U>
  23. bool operator==(const Allocator2 <T>&, const Allocator2 <U>&) noexcept { return true; }
  24. template<class T, class U>
  25. bool operator!=(const Allocator2 <T>&, const Allocator2 <U>&) noexcept { return false; }
  26. struct PointCmp {
  27. bool operator()(const int& lhs, const int& rhs ) const
  28. {
  29. return lhs==rhs;
  30. }
  31. };
  32. template < typename T>
  33. void Print( T t)
  34. {
  35. std::cout << __PRETTY_FUNCTION__ << std::endl;
  36. }
  37. int main()
  38. {
  39. using valueType = std::map< int, int>::value_type;
  40. Print( valueType{} );
  41. std::map< int, int , PointCmp, Allocator2< valueType>> m;
  42. for ( unsigned int n = 0; n<1000; n++ )
  43. {
  44. std::cout << "Now set " << n << std::endl;
  45. m[n]=n;
  46. }
  47. }

谁能指出rebind_alloc的设置?也许也是一个提示,除了看到节点分配给我的Map类型之外,还缺少了什么?

pw136qt2

pw136qt21#

如何编写自定义分配器?
你刚刚做了。
正如其他人在评论中指出的那样,rebind_alloc对于您的分配器来说是不需要的。
但你的比较器坏了。当Map通过! comp(a,b) && ! comp(b,a)检查等价性时,使用比较器,任何两个元素都被认为是等价的,除非它们相等。这是不对的。也许这就是为什么你认为你的分配器有问题的原因。然而,当所有的数字都相等时,只插入第一个数字而不插入其他数字是正确的。
请注意,当您可以使用std::less<>时,不需要定义自定义比较器。
修复这个问题并添加includes你的allocater就可以正常工作了:

  1. #include <type_traits>
  2. #include <memory>
  3. #include <iostream>
  4. #include <limits>
  5. #include <map>
  6. template <class T>
  7. class Allocator2
  8. {
  9. public:
  10. using value_type = T;
  11. using size_type = std::size_t;
  12. using difference_type = std::ptrdiff_t ;
  13. using propagate_on_container_move_assignment = std::true_type;
  14. T* allocate(size_type n, const void* hint = 0)
  15. {
  16. std::cout << "Alloc" << n << std::endl;
  17. return static_cast<T*>(malloc(n*sizeof(T)));
  18. }
  19. void deallocate(T* p, size_type n) { free( p); }
  20. size_type max_size() const { return size_type(std::numeric_limits<unsigned int>::max() / sizeof(T)); }
  21. void construct(T* p, const T& value) { _construct(p, value); }
  22. void destroy(T* p) { _destroy(p); }
  23. };
  24. template<class T, class U>
  25. bool operator==(const Allocator2 <T>&, const Allocator2 <U>&) noexcept { return true; }
  26. template<class T, class U>
  27. bool operator!=(const Allocator2 <T>&, const Allocator2 <U>&) noexcept { return false; }
  28. struct PointCmp {
  29. bool operator()(const int& lhs, const int& rhs ) const
  30. {
  31. return lhs < rhs;
  32. }
  33. };
  34. template < typename T>
  35. void Print( T t)
  36. {
  37. std::cout << __PRETTY_FUNCTION__ << std::endl;
  38. }
  39. int main()
  40. {
  41. using valueType = std::map< int, int>::value_type;
  42. Print( valueType{} );
  43. std::map< int, int , std::less<>, Allocator2< valueType>> m;
  44. for ( unsigned int n = 0; n<10; n++ )
  45. {
  46. std::cout << "Now set " << n << std::endl;
  47. m[n]=n;
  48. }
  49. }

Live Demo

展开查看全部

相关问题