Unit tests for parse_common_args()
[alexxy/gromacs.git] / src / gromacs / utility / arrayref.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares gmx::ArrayRef and gmx::ConstArrayRef.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_utility
42  */
43 #ifndef GMX_UTILITY_ARRAYREF_H
44 #define GMX_UTILITY_ARRAYREF_H
45
46 #include <cstddef>
47
48 #include <iterator>
49 #include <stdexcept>
50 #include <utility>
51 #include <vector>
52
53 #include "gmxassert.h"
54
55 namespace gmx
56 {
57
58 /*! \brief
59  * Tag type to initialize empty array references.
60  *
61  * This type (together with appropriate constructors in ArrayRef and
62  * ConstArrayRef) allows initializing any array reference to an empty value
63  * without explicitly specifying its type.  This is convenient when calling
64  * a function that takes an array reference, where constructing an empty
65  * reference explicitly would otherwise require specifying the full array
66  * reference type, including the template parameter.
67  */
68 struct EmptyArrayRef {};
69
70 /*! \brief
71  * STL-like container for an interface to a C array (or part of a std::vector).
72  *
73  * \tparam T  Value type of elements.
74  *
75  * This class provides an interface similar to \c std::vector<T>, with the
76  * following main differences:
77  *  - This class does not have its own storage.  Instead, it references an
78  *    existing array of values (either a C-style array or part of an existing
79  *    std::vector<T>).
80  *  - It is only possible to modify the values themselves through ArrayRef;
81  *    it is not possible to add or remove values.
82  *  - Copying objects of this type is cheap, and the copies behave identically
83  *    to the original object: the copy references the same set of values.
84  *
85  * This class is useful for writing wrappers that expose a different view of
86  * the internal data stored as a single vector/array.
87  *
88  * Methods in this class do not throw, except where indicated.
89  *
90  * Note that due to a Doxygen limitation, the constructor that takes a C array
91  * whose size is known at compile time does not appear in the documentation.
92  *
93  * \todo
94  * This class is not complete.  At least, it should be possible to convert an
95  * ArrayRef to a ConstArrayRef.  There are likely also methods missing (not
96  * required for current usage).
97  *
98  * \inpublicapi
99  * \ingroup module_utility
100  */
101 template <typename T>
102 class ArrayRef
103 {
104     public:
105         //! Type of values stored in the container.
106         typedef T         value_type;
107         //! Type for representing size of the container.
108         typedef size_t    size_type;
109         //! Type for representing difference between two container indices.
110         typedef ptrdiff_t difference_type;
111         //! Const reference to a container element.
112         typedef const T  &const_reference;
113         //! Const pointer to a container element.
114         typedef const T  *const_pointer;
115         //! Const iterator type for the container.
116         typedef const T  *const_iterator;
117         //! Reference to a container element.
118         typedef T        &reference;
119         //! Pointer to a container element.
120         typedef T        *pointer;
121         //! Iterator type for the container.
122         typedef T        *iterator;
123         //! Standard reverse iterator.
124         typedef std::reverse_iterator<iterator>       reverse_iterator;
125         //! Standard reverse iterator.
126         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
127
128         /*! \brief
129          * Constructs an empty reference.
130          */
131         ArrayRef() : begin_(NULL), end_(NULL) {}
132         /*! \brief
133          * Constructs an empty reference.
134          *
135          * This is provided for convenience, such that EmptyArrayRef can be
136          * used to initialize any ArrayRef, without specifying the template
137          * type.  It is not explicit to enable that usage.
138          */
139         ArrayRef(const EmptyArrayRef &) : begin_(NULL), end_(NULL) {}
140         /*! \brief
141          * Constructs a reference to a particular range.
142          *
143          * \param[in] begin  Pointer to the beginning of a range.
144          * \param[in] end    Pointer to the end of a range.
145          *
146          * Passed pointers must remain valid for the lifetime of this object.
147          */
148         ArrayRef(pointer begin, pointer end)
149             : begin_(begin), end_(end)
150         {
151             GMX_ASSERT(end >= begin, "Invalid range");
152         }
153         /*! \brief
154          * Constructs a reference to a particular range in a std::vector.
155          *
156          * \param[in] begin  Iterator to the beginning of a range.
157          * \param[in] end    Iterator to the end of a range.
158          *
159          * The referenced vector must remain valid and not be reallocated for
160          * the lifetime of this object.
161          */
162         ArrayRef(typename std::vector<value_type>::iterator begin,
163                  typename std::vector<value_type>::iterator end)
164             : begin_((begin != end) ? &*begin : NULL),
165               end_(begin_+(end-begin))
166         {
167             GMX_ASSERT(end >= begin, "Invalid range");
168         }
169         /*! \brief
170          * Constructs a reference to an array.
171          *
172          * \param[in] begin  Pointer to the beginning of the array.
173          *      May be NULL if \p size is zero.
174          * \param[in] size   Number of elements in the array.
175          *
176          * Passed pointer must remain valid for the lifetime of this object.
177          */
178         ArrayRef(pointer begin, size_type size)
179             : begin_(begin), end_(begin + size)
180         {
181         }
182         //! \cond
183         // Doxygen 1.8.5 doesn't parse the declaration correctly...
184         /*! \brief
185          * Constructs a reference to a C array.
186          *
187          * \param[in] array  C array to reference.
188          * \tparam    count  Deduced number of elements in \p array.
189          *
190          * This constructor can only be used with a real array (not with a
191          * pointer).  It constructs a reference to the whole array, without
192          * a need to pass the number of elements explicitly.  The compiler
193          * must be able to deduce the array size.
194          *
195          * Passed array must remain valid for the lifetime of this object.
196          *
197          * This constructor is not explicit to allow directly passing
198          * a C array to a function that takes an ArrayRef parameter.
199          */
200         template <size_t count>
201         ArrayRef(value_type (&array)[count])
202             : begin_(array), end_(array + count)
203         {
204         }
205         //! \endcond
206
207         //! Returns an iterator to the beginning of the container.
208         iterator begin() { return begin_; }
209         //! Returns an iterator to the beginning of the container.
210         const_iterator begin() const { return begin_; }
211         //! Returns an iterator to the end of the container.
212         iterator end() { return end_; }
213         //! Returns an iterator to the end of the container.
214         const_iterator end() const { return end_; }
215         //! Returns an iterator to the reverse beginning of the container.
216         iterator rbegin() { return reverse_iterator(end()); }
217         //! Returns an iterator to the reverse beginning of the container.
218         const_iterator rbegin() const { return reverse_iterator(end()); }
219         //! Returns an iterator to the reverse end of the container.
220         iterator rend() { return reverse_iterator(begin()); }
221         //! Returns an iterator to the reverse end of the container.
222         const_iterator rend() const { return reverse_iterator(begin()); }
223
224         //! Returns the size of the container.
225         size_type size() const { return end_ - begin_; }
226         //! Identical to size().
227         size_type capacity() const { return end_ - begin_; }
228         //! Whether the container is empty.
229         bool empty() const { return begin_ == end_; }
230
231         //! Access container element.
232         reference operator[](size_type n) { return begin_[n]; }
233         //! Access container element.
234         const_reference operator[](size_type n) const { return begin_[n]; }
235         //! Access container element (throws on out-of-range error).
236         reference at(size_type n)
237         {
238             if (n >= size())
239             {
240                 throw std::out_of_range("Vector index out of range");
241             }
242             return begin_[n];
243         }
244         //! Access container element (throws on out-of-range error).
245         const_reference at(size_type n) const
246         {
247             if (n >= size())
248             {
249                 throw std::out_of_range("Vector index out of range");
250             }
251             return begin_[n];
252         }
253         //! Returns the first element in the container.
254         reference front() { return *begin_; }
255         //! Returns the first element in the container.
256         const_reference front() const { return *begin_; }
257         //! Returns the last element in the container.
258         reference back() { return *(end_ - 1); }
259         //! Returns the last element in the container.
260         const_reference back() const { return *(end_ - 1); }
261
262         //! Returns a raw pointer to the contents of the array.
263         pointer data() { return begin_; }
264         //! Returns a raw pointer to the contents of the array.
265         const_pointer data() const { return begin_; }
266
267         /*! \brief
268          * Swaps referenced memory with the other object.
269          *
270          * The actual memory areas are not modified, only the references are
271          * swapped.
272          */
273         void swap(ArrayRef<T> &other)
274         {
275             std::swap(begin_, other.begin_);
276             std::swap(end_, other.end_);
277         }
278
279     private:
280         pointer           begin_;
281         pointer           end_;
282 };
283
284 /*! \brief
285  * STL-like container for non-mutable interface to a C array (or part of a
286  * std::vector).
287  *
288  * \tparam T  Value type of elements.
289  *
290  * This class provides an interface similar to \c std::vector<T>, with the
291  * following main differences:
292  *  - This class does not have its own storage.  Instead, it references an
293  *    existing array of values (either a C-style array or part of an existing
294  *    std::vector<T>).
295  *  - Only const methods are provided to access the stored values.
296  *    It is not possible to alter the referenced array.
297  *  - Copying objects of this type is cheap, and the copies behave identically
298  *    to the original object: the copy references the same set of values.
299  *
300  * This class is useful for writing wrappers that expose a different view of
301  * the internal data stored as a single vector/array.
302  *
303  * Methods in this class do not throw, except where indicated.
304  *
305  * Note that due to a Doxygen limitation, the constructor that takes a C array
306  * whose size is known at compile time does not appear in the documentation.
307  *
308  * \inpublicapi
309  * \ingroup module_utility
310  */
311 template <typename T>
312 class ConstArrayRef
313 {
314     public:
315         //! Type of values stored in the container.
316         typedef T         value_type;
317         //! Type for representing size of the container.
318         typedef size_t    size_type;
319         //! Type for representing difference between two container indices.
320         typedef ptrdiff_t difference_type;
321         //! Const reference to a container element.
322         typedef const T  &const_reference;
323         //! Const pointer to a container element.
324         typedef const T  *const_pointer;
325         //! Const iterator type for the container.
326         typedef const T  *const_iterator;
327         //! Equal to \a const_reference since changes are not allowed.
328         typedef const_reference reference;
329         //! Equal to \a const_pointer since changes are not allowed.
330         typedef const_pointer   pointer;
331         //! Equal to \a const_iterator since changes are not allowed.
332         typedef const_iterator  iterator;
333         //! Standard reverse iterator.
334         typedef std::reverse_iterator<iterator>       reverse_iterator;
335         //! Standard reverse iterator.
336         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
337
338         /*! \brief
339          * Constructs an empty reference.
340          */
341         ConstArrayRef() : begin_(NULL), end_(NULL) {}
342         /*! \brief
343          * Constructs an empty reference.
344          *
345          * This is provided for convenience, such that EmptyArrayRef can be
346          * used to initialize any Const ArrayRef, without specifying the
347          * template type.  It is not explicit to enable that usage.
348          */
349         ConstArrayRef(const EmptyArrayRef &) : begin_(NULL), end_(NULL) {}
350         /*! \brief
351          * Constructs a reference to a particular range.
352          *
353          * \param[in] begin  Pointer to the beginning of a range.
354          * \param[in] end    Pointer to the end of a range.
355          *
356          * Passed pointers must remain valid for the lifetime of this object.
357          */
358         ConstArrayRef(const_pointer begin, const_pointer end)
359             : begin_(begin), end_(end)
360         {
361             GMX_ASSERT(end >= begin, "Invalid range");
362         }
363         /*! \brief
364          * Constructs a reference to a particular range in a std::vector.
365          *
366          * \param[in] begin  Iterator to the beginning of a range.
367          * \param[in] end    Iterator to the end of a range.
368          *
369          * The referenced vector must remain valid and not be reallocated for
370          * the lifetime of this object.
371          */
372         ConstArrayRef(typename std::vector<value_type>::const_iterator begin,
373                       typename std::vector<value_type>::const_iterator end)
374             : begin_((begin != end) ? &*begin : NULL),
375               end_(begin_+(end-begin))
376         {
377             GMX_ASSERT(end >= begin, "Invalid range");
378         }
379         /*! \brief
380          * Constructs a reference to an array.
381          *
382          * \param[in] begin  Pointer to the beginning of the array.
383          *      May be NULL if \p size is zero.
384          * \param[in] size   Number of elements in the array.
385          *
386          * Passed pointer must remain valid for the lifetime of this object.
387          */
388         ConstArrayRef(const_pointer begin, size_type size)
389             : begin_(begin), end_(begin + size)
390         {
391         }
392         //! \cond
393         // Doxygen 1.8.5 doesn't parse the declaration correctly...
394         /*! \brief
395          * Constructs a reference to a C array.
396          *
397          * \param[in] array  C array to reference.
398          * \tparam    count  Deduced number of elements in \p array.
399          *
400          * This constructor can only be used with a real array (not with a
401          * pointer).  It constructs a reference to the whole array, without
402          * a need to pass the number of elements explicitly.  The compiler
403          * must be able to deduce the array size.
404          * Passed array must remain valid for the lifetime of this object.
405          *
406          * This constructor is not explicit to allow directly passing
407          * a C array to a function that takes a ConstArrayRef parameter.
408          */
409         template <size_t count>
410         ConstArrayRef(const value_type (&array)[count])
411             : begin_(array), end_(array + count)
412         {
413         }
414         //! \endcond
415
416         //! Returns an iterator to the beginning of the container.
417         const_iterator begin() const { return begin_; }
418         //! Returns an iterator to the end of the container.
419         const_iterator end() const { return end_; }
420         //! Returns an iterator to the reverse beginning of the container.
421         const_iterator rbegin() const { return reverse_iterator(end()); }
422         //! Returns an iterator to the reverse end of the container.
423         const_iterator rend() const { return reverse_iterator(begin()); }
424
425         //! Returns the size of the container.
426         size_type size() const { return end_ - begin_; }
427         //! Identical to size().
428         size_type capacity() const { return end_ - begin_; }
429         //! Whether the container is empty.
430         bool empty() const { return begin_ == end_; }
431
432         //! Access container element.
433         const_reference operator[](size_type n) const { return begin_[n]; }
434         //! Access container element (throws on out-of-range error).
435         const_reference at(size_type n) const
436         {
437             if (n >= size())
438             {
439                 throw std::out_of_range("Vector index out of range");
440             }
441             return begin_[n];
442         }
443         //! Returns the first element in the container.
444         const_reference front() const { return *begin_; }
445         //! Returns the last element in the container.
446         const_reference back() const { return *(end_ - 1); }
447
448         //! Returns a raw pointer to the contents of the array.
449         const_pointer data() const { return begin_; }
450
451         /*! \brief
452          * Swaps referenced memory with the other object.
453          *
454          * The actual memory areas are not modified, only the references are
455          * swapped.
456          */
457         void swap(ConstArrayRef<T> &other)
458         {
459             std::swap(begin_, other.begin_);
460             std::swap(end_, other.end_);
461         }
462
463     private:
464         const_pointer           begin_;
465         const_pointer           end_;
466 };
467
468 /*! \brief
469  * Simple swap method for ArrayRef objects.
470  *
471  * \see ArrayRef::swap()
472  *
473  * \ingroup module_utility
474  */
475 template <typename T>
476 void swap(ArrayRef<T> &a, ArrayRef<T> &b)
477 {
478     a.swap(b);
479 }
480
481 /*! \brief
482  * Simple swap method for ConstArrayRef objects.
483  *
484  * \see ConstArrayRef::swap()
485  *
486  * \ingroup module_utility
487  */
488 template <typename T>
489 void swap(ConstArrayRef<T> &a, ConstArrayRef<T> &b)
490 {
491     a.swap(b);
492 }
493
494 } // namespace gmx
495
496 #endif