fixed_vector.h.xml 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <chapter xml:id="fixed_vector.h">
  2. <title><tt>__vic/fixed_vector.h</tt></title>
  3. <chapter xml:id="fixed_vector">
  4. <title><tt>fixed_vector</tt></title>
  5. <code-block lang="C++"><![CDATA[
  6. template<class T>
  7. class fixed_vector : private non_copyable
  8. {
  9. public:
  10. using value_type = T;
  11. using iterator = ]]><nt>&lt;implementation-defined></nt><![CDATA[;
  12. using const_iterator = ]]><nt>&lt;implementation-defined></nt><![CDATA[;
  13. fixed_vector();
  14. explicit fixed_vector(size_t max_size);
  15. ~fixed_vector();
  16. // BEGIN C++11
  17. fixed_vector(fixed_vector &&o) noexcept;
  18. fixed_vector &operator=(fixed_vector &&o) noexcept;
  19. template<class... Args> T &emplace_back(Args &&... args)
  20. // END C++11
  21. // size in objects
  22. size_t size() const;
  23. size_t capacity() const;
  24. bool full() const;
  25. bool empty() const;
  26. void recreate(size_t new_max_size, bool size_exact = false);
  27. void *alloc(); // returns pointer to memory for object allocation
  28. void push_allocated(); // adds last allocated object to the container
  29. void pop_back();
  30. void clear();
  31. void swap(fixed_vector &o) noexcept;
  32. // element access
  33. T &operator[](size_t i);
  34. iterator begin();
  35. iterator end();
  36. T &front();
  37. T &back();
  38. const T &operator[](size_t i) const;
  39. const_iterator begin() const;
  40. const_iterator end() const;
  41. const_iterator cbegin() const;
  42. const_iterator cend() const;
  43. const T &front() const;
  44. const T &back() const;
  45. };
  46. template<class T>
  47. void swap(fixed_vector<T> &o1, fixed_vector<T> &o2) noexcept;
  48. ]]></code-block>
  49. <p>The standard containers in C++98 don't allow to store non-copiable elements.
  50. Even in C++11 elements of containers like <tt>std::vector</tt> have to be at
  51. least noexcept movable. This class solves the problem. It is a dynamic array
  52. for non-copyable objects or just <tt>std::vector</tt> without autogrowing
  53. <tt>capacity()</tt>.</p>
  54. <p>Without <tt>emplace_back()</tt> it is impossible to create arbitrary new
  55. object right in the container's memory. C++98 lacks forwarding references so it
  56. is ear impossible to pass arbitrary parameters to the element's constructor.
  57. <tt>fixed_vector</tt> overcomes this problem using the following mechanism.
  58. The new element is created using several phases:</p>
  59. <list style="numbered">
  60. <item>Requesting memory for the new element in the container -
  61. <tt>alloc()</tt>,</item>
  62. <item>Creation of the object using placement new -
  63. <tt>new(ptr) type(...)</tt>,</item>
  64. <item>Fixation of the newly created object in the container -
  65. <tt>push_allocated()</tt>.</item>
  66. </list>
  67. <p>See the example at the end of the article.</p>
  68. <p>Maximum capacity is specified on creation of the container. Later it
  69. can be changed but all the elements has to be destroyed before. In other words,
  70. the container can be recreated (<tt>recreate()</tt> function).</p>
  71. <p>When available, <tt>emplace_back()</tt> must be used for elements creation.
  72. If not, the unsafe interface described above must be used with care. It is very
  73. ugly and error-prone but solves the task. After the element is created in the
  74. container, you operate with it almost as easy as with any other copyable object
  75. in the standard container. Anyway, it is more efficient and convenient to use
  76. in general than alternative approaches like creating the objects on the free
  77. store and placing only pointers to the container, even if we have
  78. <tt>std::unique_ptr</tt> to manage lifetime of the objects.</p>
  79. <p>Fundamental differences from <tt>std::vector</tt>:</p>
  80. <list style="numbered">
  81. <item>Elements don't have to be copyable or movable (<tt>std::vector</tt>
  82. requires at least noexcept-movability);</item>
  83. <item>Elements have stable addresses after addition of new element;</item>
  84. <item><tt>emplace_back()</tt> has precondition (<tt>!full()</tt>).</item>
  85. </list>
  86. <section><title>Class members</title>
  87. <synopsis>
  88. <prototype>typename value_type</prototype>
  89. <p>Type of the elements.</p>
  90. </synopsis>
  91. <synopsis>
  92. <prototype>typename iterator</prototype>
  93. <prototype>typename const_iterator</prototype>
  94. <p>Iterators.</p>
  95. </synopsis>
  96. <synopsis>
  97. <prototype>fixed_vector()</prototype>
  98. <p>Create the object without memory allocation.</p>
  99. <postcondition><tt>capacity() == 0</tt></postcondition>
  100. </synopsis>
  101. <synopsis>
  102. <prototype>explicit fixed_vector(size_t max_size)</prototype>
  103. <p>Allocates memory for <tt>max_size</tt> elements.</p>
  104. <postcondition><tt>capacity() == max_size</tt></postcondition>
  105. </synopsis>
  106. <synopsis>
  107. <prototype>~fixed_vector()</prototype>
  108. <p>Calls <tt>clear()</tt>.</p>
  109. </synopsis>
  110. <synopsis>
  111. <prototype>fixed_vector(fixed_vector &amp;&amp;o) noexcept <sign>C++11</sign></prototype>
  112. <prototype>fixed_vector &amp;operator=(fixed_vector &amp;&amp;o) noexcept <sign>C++11</sign></prototype>
  113. <p>Move operations for C++11 mode.</p>
  114. </synopsis>
  115. <synopsis>
  116. <prototype>size_t size() const</prototype>
  117. <prototype>size_t capacity() const</prototype>
  118. <p>Current size and capacity of the container.</p>
  119. </synopsis>
  120. <synopsis>
  121. <prototype>bool empty() const</prototype>
  122. <p>Returns <tt>size() == 0</tt>.</p>
  123. </synopsis>
  124. <synopsis>
  125. <prototype>bool full() const</prototype>
  126. <p>Returns <tt>size() == capacity()</tt>.</p>
  127. </synopsis>
  128. <synopsis>
  129. <prototype>void recreate(size_t new_max_size, bool size_exact = false)</prototype>
  130. <p>Recreates the container. At first calls <tt>clear()</tt>, then reallocates
  131. memory buffer if <tt>new_max_size > capacity()</tt> or <tt>size_exact</tt> is
  132. <tt>true</tt> and <tt>new_max_size != capacity()</tt>.</p>
  133. <postcondition><tt>capacity() >= new_max_size &amp;&amp; empty() == true</tt>
  134. (if <tt>size_exact == true</tt> then <tt>capacity() == new_max_size &amp;&amp;
  135. empty() == true</tt>)</postcondition>
  136. </synopsis>
  137. <synopsis>
  138. <prototype>void *alloc()</prototype>
  139. <p>Returns the raw memory block where new instance of <tt>value_type</tt>
  140. can be allocated.</p>
  141. <precondition><tt>!full()</tt></precondition>
  142. <note>Use <tt>emplace_back()</tt> in C++11 mode.</note>
  143. </synopsis>
  144. <synopsis>
  145. <prototype>void push_allocated()</prototype>
  146. <p>This call right after <tt>alloc()</tt> adds the just created object to the
  147. container.</p>
  148. </synopsis>
  149. <synopsis>
  150. <prototype>template&lt;class... Args> T &amp;emplace_back(Args &amp;&amp;... args) <sign>C++11</sign></prototype>
  151. <p>Constructs new object and adds it to the container (<tt>alloc()</tt> +
  152. <tt>new</tt> + <tt>push_allocated()</tt> with a single call). A reference to
  153. the new object is returned.</p>
  154. <precondition><tt>!full()</tt></precondition>
  155. </synopsis>
  156. <synopsis>
  157. <prototype>void pop_back()</prototype>
  158. <p>Remove the last element from the container.</p>
  159. <precondition><tt>!empty()</tt></precondition>
  160. </synopsis>
  161. <synopsis>
  162. <prototype>void clear()</prototype>
  163. <p>Destroys the elements in the reverse order they were created.</p>
  164. <postcondition><tt>size() == 0</tt> (<tt>empty() == true</tt>)</postcondition>
  165. </synopsis>
  166. <synopsis>
  167. <prototype>void swap(fixed_vector &amp;o)</prototype>
  168. <prototype><![CDATA[template<class T> void swap(fixed_vector<T> &o1, fixed_vector<T> &o2) noexcept]]></prototype>
  169. <p>Swaps the value with <tt>o</tt>.</p>
  170. </synopsis>
  171. <synopsis>
  172. <prototype>T &amp;operator[](size_t i)</prototype>
  173. <prototype>const T &amp;operator[](size_t i) const</prototype>
  174. <p>Access to the elements by index.</p>
  175. <precondition><tt>i &lt; size()</tt></precondition>
  176. </synopsis>
  177. <synopsis>
  178. <prototype>T &amp;front()</prototype>
  179. <prototype>const T &amp;front() const</prototype>
  180. <prototype>T &amp;back()</prototype>
  181. <prototype>const T &amp;back() const</prototype>
  182. <p>Access to the first and the last elements.</p>
  183. <precondition><tt>!empty()</tt></precondition>
  184. </synopsis>
  185. <synopsis>
  186. <prototype>iterator begin()</prototype>
  187. <prototype>const_iterator begin() const</prototype>
  188. <prototype>const_iterator cbegin() const</prototype>
  189. <prototype>iterator end()</prototype>
  190. <prototype>const_iterator end() const</prototype>
  191. <prototype>const_iterator cend() const</prototype>
  192. <p>Access to the elements via iterators.</p>
  193. </synopsis>
  194. </section>
  195. <section><title>Example</title>
  196. <code-block lang="C++"><![CDATA[
  197. // Creating vector for 2 objects of class C
  198. __vic::fixed_vector<C> v(2);
  199. // Creating new object in C++98 mode:
  200. new(v.alloc()) C(...); // Request memory and construct the object
  201. v.push_allocated(); // Fixate successfully created object in the container
  202. // Creating new object in C++11 mode:
  203. v.emplace_back(...);
  204. ]]></code-block>
  205. </section>
  206. </chapter>
  207. </chapter>