fork download
  1. #include <memory>
  2. #include <algorithm>
  3. #include <cassert>
  4. #include <iostream>
  5.  
  6. template <typename T, std::size_t N>
  7. class tiny_buffer {
  8. public:
  9.  
  10. typedef T value_type;
  11. typedef value_type * iterator;
  12. typedef const value_type * const_iterator;
  13.  
  14. tiny_buffer()
  15. : size_(0)
  16. {}
  17.  
  18. tiny_buffer(std::size_t n, const value_type & v)
  19. : size_(n)
  20. {
  21. std::uninitialized_fill(begin(), end(), v);
  22. }
  23.  
  24. tiny_buffer(std::size_t n)
  25. : size_(n)
  26. {
  27. std::uninitialized_fill(begin(), end(), (value_type()));
  28. }
  29.  
  30. ~tiny_buffer()
  31. { shrink(0); }
  32.  
  33. template <typename S, std::size_t M>
  34. tiny_buffer(const tiny_buffer<S, M> & rhs)
  35. : size_(rhs.size())
  36. {
  37. check_size(size_);
  38. std::uninitialized_copy(rhs.begin(), rhs.end(), begin());
  39. }
  40.  
  41. template <typename S, std::size_t M>
  42. tiny_buffer & operator=(const tiny_buffer<S, M> & rhs)
  43. {
  44. const std::size_t new_size = rhs.size();
  45.  
  46. if (new_size < size_) {
  47. shrink(new_size);
  48. std::copy(rhs.begin(), rhs.end(), begin());
  49. } else {
  50. check_size(new_size);
  51. std::copy(rhs.begin(), rhs.begin() + size_, begin());
  52. std::uninitialized_copy(rhs.begin() + size_, rhs.end(), end());
  53. size_ = new_size;
  54. }
  55. }
  56.  
  57. value_type & operator[](std::size_t i)
  58. { return data()[i]; }
  59.  
  60. const value_type & operator[](std::size_t i) const
  61. { return data()[i]; }
  62.  
  63. value_type & at(std::size_t i)
  64. {
  65. check_index(i);
  66. return (*this)[i];
  67. }
  68.  
  69. const value_type & at(std::size_t i) const
  70. {
  71. check_index(i);
  72. return (*this)[i];
  73. }
  74.  
  75. iterator begin()
  76. { return data(); }
  77.  
  78. iterator end()
  79. { return data() + size_; }
  80.  
  81. const_iterator begin() const
  82. { return data(); }
  83.  
  84. const_iterator end() const
  85. { return data() + size_; }
  86.  
  87. std::size_t size() const
  88. { return size_; }
  89.  
  90. void push_back(const value_type & v)
  91. {
  92. check_size(size_ + 1);
  93. new(data() + size_) value_type(v);
  94. ++size_;
  95. }
  96.  
  97. void shrink(std::size_t new_size)
  98. {
  99. assert(new_size <= size_);
  100. for (std::size_t i = new_size; i < size_; ++i) {
  101. data()[i].~value_type();
  102. }
  103. size_ = new_size;
  104. }
  105.  
  106. private:
  107. char raw_data_[sizeof(T) * N];
  108. std::size_t size_;
  109.  
  110. T * data()
  111. { return reinterpret_cast<T*>(raw_data_); }
  112.  
  113. const T * data() const
  114. { return reinterpret_cast<const T*>(raw_data_); }
  115.  
  116. void check_index(std::size_t i) const
  117. { assert(i < size() && "Buffer index out of bounds"); }
  118.  
  119. void check_size(std::size_t s) const
  120. { assert(s <= N && "Buffer size exceeds capacity"); }
  121. };
  122.  
  123. // Testing
  124.  
  125. static int cnt;
  126.  
  127. struct tracer
  128. {
  129. tracer() { cnt++; std::cout << "ctor\n"; }
  130. tracer(const tracer &) { cnt++; std::cout << "copy ctor\n"; };
  131. ~tracer() { cnt--; std::cout << "dtor\n"; }
  132. };
  133.  
  134. int main()
  135. {
  136. tiny_buffer<int, 5> a;
  137. assert(a.size() == 0);
  138. a.push_back(3);
  139. assert(a[0] == 3);
  140. assert(a.size() == 1);
  141.  
  142. tiny_buffer<short, 3> b(3, 1);
  143. a = b;
  144.  
  145. assert(b.size() == 3);
  146. assert(a.size() == b.size());
  147. assert(a[0] == 1 && a[1] == 1 && a[2] == 1);
  148.  
  149. tiny_buffer<int, 5> c(b);
  150. assert(c.size() == b.size());
  151. assert(c[0] == 1 && c[1] == 1 && c[2] == 1);
  152.  
  153. tiny_buffer<tracer, 3> ts(2);
  154. assert(ts.size() == 2);
  155. assert(cnt == ts.size());
  156.  
  157. ts.shrink(1);
  158. assert(ts.size() == 1);
  159. assert(cnt == 1);
  160.  
  161. ts.push_back((tracer()));
  162.  
  163. return 0;
  164. }
  165.  
Success #stdin #stdout 0s 3300KB
stdin
Standard input is empty
stdout
ctor
copy ctor
copy ctor
dtor
dtor
ctor
copy ctor
dtor
dtor
dtor