make_array_helper.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2012 Glen Joseph Fernandes
  3. * glenfe at live dot com
  4. *
  5. * Distributed under the Boost Software License,
  6. * Version 1.0. (See accompanying file LICENSE_1_0.txt
  7. * or copy at http://boost.org/LICENSE_1_0.txt)
  8. */
  9. #ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
  10. #define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
  11. #include <boost/type_traits/alignment_of.hpp>
  12. namespace boost {
  13. namespace detail {
  14. template<typename T, typename Y = char>
  15. class make_array_helper;
  16. template<typename T, typename Y>
  17. class make_array_helper<T[], Y> {
  18. template<typename T2, typename Y2>
  19. friend class make_array_helper;
  20. public:
  21. typedef Y value_type;
  22. typedef Y* pointer;
  23. typedef const Y* const_pointer;
  24. typedef Y& reference;
  25. typedef const Y& const_reference;
  26. typedef std::size_t size_type;
  27. typedef ptrdiff_t difference_type;
  28. template<typename U>
  29. struct rebind {
  30. typedef make_array_helper<T[], U> other;
  31. };
  32. make_array_helper(std::size_t size_, T** data_)
  33. : size(sizeof(T) * size_),
  34. data(data_) {
  35. }
  36. template<class U>
  37. make_array_helper(const make_array_helper<T[], U>& other)
  38. : size(other.size),
  39. data(other.data) {
  40. }
  41. pointer address(reference value) const {
  42. return &value;
  43. }
  44. const_pointer address(const_reference value) const {
  45. return &value;
  46. }
  47. size_type max_size() const {
  48. return static_cast<std::size_t>(-1) / sizeof(Y);
  49. }
  50. pointer allocate(size_type count, const void* = 0) {
  51. std::size_t a1 = boost::alignment_of<T>::value;
  52. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  53. void* p1 = ::operator new(n1 + size);
  54. char* p2 = static_cast<char*>(p1) + n1;
  55. while (std::size_t(p2) % a1 != 0) {
  56. p2--;
  57. }
  58. *data = reinterpret_cast<T*>(p2);
  59. return reinterpret_cast<Y*>(p1);
  60. }
  61. void deallocate(pointer memory, size_type) {
  62. void* p1 = memory;
  63. ::operator delete(p1);
  64. }
  65. void construct(pointer memory, const Y& value) {
  66. void* p1 = memory;
  67. ::new(p1) Y(value);
  68. }
  69. void destroy(pointer memory) {
  70. memory->~Y();
  71. }
  72. template<typename U>
  73. bool operator==(const make_array_helper<T[], U>&) const {
  74. return true;
  75. }
  76. template<typename U>
  77. bool operator!=(const make_array_helper<T[], U>& other) const {
  78. return !(*this == other);
  79. }
  80. private:
  81. std::size_t size;
  82. T** data;
  83. };
  84. template<typename T, std::size_t N, typename Y>
  85. class make_array_helper<T[N], Y> {
  86. template<typename T2, typename Y2>
  87. friend class make_array_helper;
  88. public:
  89. typedef Y value_type;
  90. typedef Y* pointer;
  91. typedef const Y* const_pointer;
  92. typedef Y& reference;
  93. typedef const Y& const_reference;
  94. typedef std::size_t size_type;
  95. typedef ptrdiff_t difference_type;
  96. template<typename U>
  97. struct rebind {
  98. typedef make_array_helper<T[N], U> other;
  99. };
  100. make_array_helper(T** data_)
  101. : data(data_) {
  102. }
  103. template<class U>
  104. make_array_helper(const make_array_helper<T[N], U>& other)
  105. : data(other.data) {
  106. }
  107. pointer address(reference value) const {
  108. return &value;
  109. }
  110. const_pointer address(const_reference value) const {
  111. return &value;
  112. }
  113. size_type max_size() const {
  114. return static_cast<std::size_t>(-1) / sizeof(Y);
  115. }
  116. pointer allocate(size_type count, const void* = 0) {
  117. std::size_t a1 = boost::alignment_of<T>::value;
  118. std::size_t n1 = count * sizeof(Y) + a1 - 1;
  119. void* p1 = ::operator new(n1 + N1);
  120. char* p2 = static_cast<char*>(p1) + n1;
  121. while (std::size_t(p2) % a1 != 0) {
  122. p2--;
  123. }
  124. *data = reinterpret_cast<T*>(p2);
  125. return reinterpret_cast<Y*>(p1);
  126. }
  127. void deallocate(pointer memory, size_type) {
  128. void* p1 = memory;
  129. ::operator delete(p1);
  130. }
  131. void construct(pointer memory, const Y& value) {
  132. void* p1 = memory;
  133. ::new(p1) Y(value);
  134. }
  135. void destroy(pointer memory) {
  136. memory->~Y();
  137. }
  138. template<typename U>
  139. bool operator==(const make_array_helper<T[N], U>&) const {
  140. return true;
  141. }
  142. template<typename U>
  143. bool operator!=(const make_array_helper<T[N], U>& other) const {
  144. return !(*this == other);
  145. }
  146. private:
  147. enum {
  148. N1 = N * sizeof(T)
  149. };
  150. T** data;
  151. };
  152. }
  153. }
  154. #endif