siplasplas
stl_allocator.hpp
1 #ifndef SIPLASPLAS_ALLOCATOR_STL_ALLOCATOR_HPP
2 #define SIPLASPLAS_ALLOCATOR_STL_ALLOCATOR_HPP
3 
4 #include <memory>
5 
6 #include <ctti/type_id.hpp>
7 #include <sstream>
8 
9 namespace cpp
10 {
11  template<typename T, typename Allocator>
12  struct STLAllocator : public Allocator
13  {
14  using value_type = T;
15  using pointer = T*;
16  using const_pointer = const T*;
17  using reference = T&;
18  using const_reference = const T&;
19 
20  using propagate_on_container_move_assignment = std::true_type;
21 
22  STLAllocator() = default;
23  STLAllocator(const STLAllocator&) = default;
24  STLAllocator(STLAllocator&&) = default;
25 
26  STLAllocator(char* begin, char* end, std::size_t fence = 0, unsigned char cannary = 0xff) :
27  Allocator{begin, end}
28  {}
29 
30  STLAllocator(Allocator&& allocator, std::size_t fence = 0, unsigned char cannary = 0xff) :
31  Allocator{std::move(allocator)}
32  {}
33 
34  STLAllocator(const Allocator& allocator, std::size_t fence = 0, unsigned char cannary = 0xff) :
35  Allocator{allocator}
36  {}
37 
38  // Rebind-aware ctors
39 
40  template<typename U>
42  Allocator{ static_cast<const Allocator&>(alloc) }
43  {}
44 
45  template<typename U>
47  Allocator{ std::move( static_cast<const Allocator&>(alloc) ) }
48  {}
49 
50  const Allocator& raw_allocator() const
51  {
52  return *static_cast<const Allocator*>(this);
53  }
54 
55  Allocator& raw_allocator()
56  {
57  return *static_cast<Allocator*>(this);
58  }
59 
60  pointer allocate(std::size_t count)
61  {
62  const std::size_t blockSize = sizeof(value_type)*count;
63  char* user_ptr = reinterpret_cast<char*>(Allocator::allocate(blockSize, alignof(value_type)));
64 
65  if(user_ptr)
66  {
67  return reinterpret_cast<pointer>(user_ptr);
68  }
69  else
70  {
71  throw std::bad_alloc{};
72  }
73  }
74 
75  void deallocate(pointer ptr, std::size_t count)
76  {
77  Allocator::deallocate(ptr, sizeof(value_type)*count);
78  }
79 
80  template<typename... Args>
81  void construct(pointer ptr, Args&&... args)
82  {
83  new(ptr) value_type{std::forward<Args>(args)...};
84  }
85 
86  void destroy(pointer ptr)
87  {
88  ptr->~value_type();
89  }
90 
91  template<typename U>
92  struct rebind
93  {
95  };
96 
97  friend bool operator==(const STLAllocator& lhs, const STLAllocator& rhs)
98  {
99  return lhs.raw_allocator() == rhs.raw_allocator();
100  }
101 
102  friend bool operator!=(const STLAllocator& lhs, const STLAllocator& rhs)
103  {
104  return !(lhs == rhs);
105  }
106 
107  std::string dump() const
108  {
109  std::ostringstream os;
110 
111  os << "STLAllocator adapter for " << ctti::type_id<Allocator>().name() << ": \n"
112  " - Type: " << ctti::type_id<T>().name() << " (" << sizeof(T) << " bytes, alignment: " << alignof(T) << ")\n"
113  << Allocator::dump();
114 
115  return os.str();
116  }
117  };
118 
119  template<typename T, typename Allocator>
120  cpp::STLAllocator<T, std::decay_t<Allocator>> make_stl_allocator(Allocator&& alloc)
121  {
122  return { std::forward<Allocator>(alloc) };
123  }
124 }
125 
126 #endif // SIPLASPLAS_ALLOCATOR_STL_ALLOCATOR_HPP
127 
Definition: messaging.hpp:8
Definition: stl_allocator.hpp:12
constexpr auto end(const Sequence &sequence)
Returns an iterator pointing to the end of a sequence.
Definition: algorithm.hpp:86
constexpr auto begin(const Sequence &sequence)
Returns an iterator pointing to the beginning of a sequence.
Definition: algorithm.hpp:62
Definition: stl_allocator.hpp:92