Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / utility / arrayref.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \file
32  * \brief
33  * Declares gmx::ConstArrayRef.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_utility
38  */
39 #ifndef GMX_UTILITY_ARRAYREF_H
40 #define GMX_UTILITY_ARRAYREF_H
41
42 #include <cstddef>
43
44 #include <iterator>
45 #include <stdexcept>
46 #include <utility>
47 #include <vector>
48
49 #include "gmxassert.h"
50
51 namespace gmx
52 {
53
54 /*! \brief
55  * STL container non-mutable interface for a C array (or part of a std::vector).
56  *
57  * \tparam T  Value type of elements.
58  *
59  * This class provides an interface similar to \c std::vector<T>, with the
60  * following main differences:
61  *  - This class does not have its own storage.  Instead, it references an
62  *    existing array of values (either a C-style array or part of an existing
63  *    std::vector<T>).
64  *  - Only const methods are provided to access the stored values.
65  *    It is not possible to alter the referenced array.
66  *  - Copying objects of this type is cheap, and the copies behave identically
67  *    to the original object: the copy references the same set of values.
68  *
69  * \inpublicapi
70  * \ingroup module_utility
71  */
72 template <typename T>
73 class ConstArrayRef
74 {
75     public:
76         //! Type of values stored in the container.
77         typedef T         value_type;
78         //! Type for representing size of the container.
79         typedef size_t    size_type;
80         //! Type for representing difference between two container indices.
81         typedef ptrdiff_t difference_type;
82         //! Const reference to a container element.
83         typedef const T  &const_reference;
84         //! Const pointer to a container element.
85         typedef const T  *const_pointer;
86         //! Const iterator type for the container.
87         typedef const T  *const_iterator;
88         //! Equal to \a const_reference since changes are not allowed.
89         typedef const_reference reference;
90         //! Equal to \a const_pointer since changes are not allowed.
91         typedef const_pointer   pointer;
92         //! Equal to \a const_iterator since changes are not allowed.
93         typedef const_iterator  iterator;
94         //! Standard reverse iterator.
95         typedef std::reverse_iterator<iterator>       reverse_iterator;
96         //! Standard reverse iterator.
97         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
98
99         /*! \brief
100          * Constructs an empty reference.
101          */
102         ConstArrayRef() : begin_(NULL), end_(NULL) {}
103         /*! \brief
104          * Constructs a reference to a particular range.
105          *
106          * \param[in] begin  Pointer to the beginning of a range.
107          * \param[in] end    Pointer to the end of a range.
108          *
109          * Passed pointers must remain valid for the lifetime of this object.
110          */
111         ConstArrayRef(const_pointer begin, const_pointer end)
112             : begin_(begin), end_(end)
113         {
114             GMX_ASSERT(end >= begin, "Invalid range");
115         }
116         /*! \brief
117          * Constructs a reference to a particular rangein a std::vector.
118          *
119          * \param[in] begin  Pointer to the beginning of a range.
120          * \param[in] end    Pointer to the end of a range.
121          *
122          * The referenced vector must remain valid and not be reallocated for
123          * the lifetime of this object.
124          */
125         ConstArrayRef(typename std::vector<T>::const_iterator begin,
126                       typename std::vector<T>::const_iterator end)
127             : begin_((begin != end) ? &*begin : NULL),
128               end_(begin_+(end-begin))
129         {
130             GMX_ASSERT(end >= begin, "Invalid range");
131         }
132         /*! \brief
133          * Constructs a reference to an array.
134          *
135          * \param[in] size   Number of elements in the array.
136          * \param[in] begin  Pointer to the beginning of the array.
137          *      May be NULL if \p size is zero.
138          *
139          * Passed pointer must remain valid for the lifetime of this object.
140          */
141         ConstArrayRef(size_type size, const_pointer begin)
142             : begin_(begin), end_(begin + size)
143         {
144         }
145
146         //! Returns an interator to the beginning of the container.
147         const_iterator begin() const { return begin_; }
148         //! Returns an interator to the end of the container.
149         const_iterator end() const { return end_; }
150         //! Returns an interator to the reverse beginning of the container.
151         const_iterator rbegin() const { return reverse_iterator(end()); }
152         //! Returns an interator to the reverse end of the container.
153         const_iterator rend() const { return reverse_iterator(begin()); }
154
155         //! Returns the size of the container.
156         size_type size() const { return end_ - begin_; }
157         //! Identical to size().
158         size_type capacity() const { return end_ - begin_; }
159         //! Whether the container is empty.
160         bool empty() const { return begin_ == end_; }
161
162         //! Access container element.
163         const_reference operator[](size_type n) const { return begin_[n]; }
164         //! Access container element (throws on out-of-range error).
165         const_reference at(size_type n) const
166         {
167             if (n >= size())
168             {
169                 throw std::out_of_range("Vector index out of range");
170             }
171             return begin_[n];
172         }
173         //! Returns the first element in the container.
174         const_reference front() const { return *begin_; }
175         //! Returns the last element in the container.
176         const_reference back() const { return *(end_ - 1); }
177
178         //! Returns a raw pointer to the contents of the array.
179         const_pointer data() const { return begin_; }
180
181         /*! \brief
182          * Swaps referenced memory with the other object.
183          *
184          * The actual memory areas are not modified, only the references are
185          * swapped.
186          */
187         void swap(ConstArrayRef<T> &other)
188         {
189             std::swap(begin_, other.begin_);
190             std::swap(end_, other.end_);
191         }
192
193     private:
194         const_pointer           begin_;
195         const_pointer           end_;
196 };
197
198 /*! \brief
199  * Simple swap method for ConstArrayRef objects.
200  *
201  * \see ConstArrayRef::swap()
202  */
203 template <typename T>
204 void swap(ConstArrayRef<T> &a, ConstArrayRef<T> &b)
205 {
206     a.swap(b);
207 }
208
209 } // namespace gmx
210
211 #endif