Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / utility / arrayref.h
index 55c17017de8da90df9eb3c9f2421eb040da03010..fb4778d24a7573b6cc6d3cad83538c712c4bf7d1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -34,7 +34,7 @@
  */
 /*! \file
  * \brief
- * Declares gmx::ConstArrayRef.
+ * Declares gmx::ArrayRef and gmx::ConstArrayRef.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inpublicapi
 #include <utility>
 #include <vector>
 
-#include "gmxassert.h"
+#include "gromacs/utility/gmxassert.h"
 
 namespace gmx
 {
 
 /*! \brief
- * STL container non-mutable interface for a C array (or part of a std::vector).
+ * Tag type to initialize empty array references.
+ *
+ * This type (together with appropriate constructors in ArrayRef and
+ * ConstArrayRef) allows initializing any array reference to an empty value
+ * without explicitly specifying its type.  This is convenient when calling
+ * a function that takes an array reference, where constructing an empty
+ * reference explicitly would otherwise require specifying the full array
+ * reference type, including the template parameter.
+ */
+struct EmptyArrayRef {};
+
+/*! \brief
+ * STL-like container for an interface to a C array (or part of a std::vector).
+ *
+ * \tparam T  Value type of elements.
+ *
+ * This class provides an interface similar to \c std::vector<T>, with the
+ * following main differences:
+ *  - This class does not have its own storage.  Instead, it references an
+ *    existing array of values (either a C-style array or part of an existing
+ *    std::vector<T>).
+ *  - It is only possible to modify the values themselves through ArrayRef;
+ *    it is not possible to add or remove values.
+ *  - Copying objects of this type is cheap, and the copies behave identically
+ *    to the original object: the copy references the same set of values.
+ *
+ * This class is useful for writing wrappers that expose a different view of
+ * the internal data stored as a single vector/array.
+ *
+ * Methods in this class do not throw, except where indicated.
+ *
+ * Note that due to a Doxygen limitation, the constructor that takes a C array
+ * whose size is known at compile time does not appear in the documentation.
+ *
+ * \todo
+ * This class is not complete.  At least, it should be possible to convert an
+ * ArrayRef to a ConstArrayRef.  There are likely also methods missing (not
+ * required for current usage).
+ *
+ * \inpublicapi
+ * \ingroup module_utility
+ */
+template <typename T>
+class ArrayRef
+{
+    public:
+        //! Type of values stored in the container.
+        typedef T         value_type;
+        //! Type for representing size of the container.
+        typedef size_t    size_type;
+        //! Type for representing difference between two container indices.
+        typedef ptrdiff_t difference_type;
+        //! Const reference to a container element.
+        typedef const T  &const_reference;
+        //! Const pointer to a container element.
+        typedef const T  *const_pointer;
+        //! Const iterator type for the container.
+        typedef const T  *const_iterator;
+        //! Reference to a container element.
+        typedef T        &reference;
+        //! Pointer to a container element.
+        typedef T        *pointer;
+        //! Iterator type for the container.
+        typedef T        *iterator;
+        //! Standard reverse iterator.
+        typedef std::reverse_iterator<iterator>       reverse_iterator;
+        //! Standard reverse iterator.
+        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+        /*! \brief
+         * Constructs an empty reference.
+         */
+        ArrayRef() : begin_(NULL), end_(NULL) {}
+        /*! \brief
+         * Constructs an empty reference.
+         *
+         * This is provided for convenience, such that EmptyArrayRef can be
+         * used to initialize any ArrayRef, without specifying the template
+         * type.  It is not explicit to enable that usage.
+         */
+        ArrayRef(const EmptyArrayRef &) : begin_(NULL), end_(NULL) {}
+        /*! \brief
+         * Constructs a reference to a particular range.
+         *
+         * \param[in] begin  Pointer to the beginning of a range.
+         * \param[in] end    Pointer to the end of a range.
+         *
+         * Passed pointers must remain valid for the lifetime of this object.
+         *
+         * \note For clarity, use the non-member function arrayRefFromPointers
+         * instead.
+         */
+        ArrayRef(pointer begin, pointer end)
+            : begin_(begin), end_(end)
+        {
+            GMX_ASSERT(end >= begin, "Invalid range");
+        }
+        //! \cond
+        // Doxygen 1.8.5 doesn't parse the declaration correctly...
+        /*! \brief
+         * Constructs a reference to a C array.
+         *
+         * \param[in] array  C array to reference.
+         * \tparam    count  Deduced number of elements in \p array.
+         *
+         * This constructor can only be used with a real array (not with a
+         * pointer).  It constructs a reference to the whole array, without
+         * a need to pass the number of elements explicitly.  The compiler
+         * must be able to deduce the array size.
+         *
+         * Passed array must remain valid for the lifetime of this object.
+         *
+         * This constructor is not explicit to allow directly passing
+         * a C array to a function that takes an ArrayRef parameter.
+         */
+        template <size_t count>
+        ArrayRef(value_type (&array)[count])
+            : begin_(array), end_(array + count)
+        {
+        }
+        //! \endcond
+
+        //! Returns an iterator to the beginning of the container.
+        iterator begin() { return begin_; }
+        //! Returns an iterator to the beginning of the container.
+        const_iterator begin() const { return begin_; }
+        //! Returns an iterator to the end of the container.
+        iterator end() { return end_; }
+        //! Returns an iterator to the end of the container.
+        const_iterator end() const { return end_; }
+        //! Returns an iterator to the reverse beginning of the container.
+        iterator rbegin() { return reverse_iterator(end()); }
+        //! Returns an iterator to the reverse beginning of the container.
+        const_iterator rbegin() const { return reverse_iterator(end()); }
+        //! Returns an iterator to the reverse end of the container.
+        iterator rend() { return reverse_iterator(begin()); }
+        //! Returns an iterator to the reverse end of the container.
+        const_iterator rend() const { return reverse_iterator(begin()); }
+
+        //! Returns the size of the container.
+        size_type size() const { return end_ - begin_; }
+        //! Identical to size().
+        size_type capacity() const { return end_ - begin_; }
+        //! Whether the container is empty.
+        bool empty() const { return begin_ == end_; }
+
+        //! Access container element.
+        reference operator[](size_type n) { return begin_[n]; }
+        //! Access container element.
+        const_reference operator[](size_type n) const { return begin_[n]; }
+        //! Access container element (throws on out-of-range error).
+        reference at(size_type n)
+        {
+            if (n >= size())
+            {
+                throw std::out_of_range("Vector index out of range");
+            }
+            return begin_[n];
+        }
+        //! Access container element (throws on out-of-range error).
+        const_reference at(size_type n) const
+        {
+            if (n >= size())
+            {
+                throw std::out_of_range("Vector index out of range");
+            }
+            return begin_[n];
+        }
+        //! Returns the first element in the container.
+        reference front() { return *begin_; }
+        //! Returns the first element in the container.
+        const_reference front() const { return *begin_; }
+        //! Returns the last element in the container.
+        reference back() { return *(end_ - 1); }
+        //! Returns the last element in the container.
+        const_reference back() const { return *(end_ - 1); }
+
+        //! Returns a raw pointer to the contents of the array.
+        pointer data() { return begin_; }
+        //! Returns a raw pointer to the contents of the array.
+        const_pointer data() const { return begin_; }
+
+        /*! \brief
+         * Swaps referenced memory with the other object.
+         *
+         * The actual memory areas are not modified, only the references are
+         * swapped.
+         */
+        void swap(ArrayRef<T> &other)
+        {
+            std::swap(begin_, other.begin_);
+            std::swap(end_, other.end_);
+        }
+
+    private:
+        pointer           begin_;
+        pointer           end_;
+};
+
+
+/*! \brief
+ * Constructs a reference to a particular range from two pointers.
+ *
+ * \param[in] begin  Pointer to the beginning of a range.
+ * \param[in] end    Pointer to the end of a range.
+ *
+ * Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromPointers(T * begin, T * end)
+{
+    return ArrayRef<T>(begin, end);
+}
+
+/*! \brief
+ * Constructs a reference to an array
+ *
+ * \param[in] begin  Pointer to the beginning of the array.
+ *                   May be NULL if \p size is zero.
+ * \param[in] size   Number of elements in the array.
+ *
+ * Passed pointer must remain valid for the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromArray(T * begin, size_t size)
+{
+    return arrayRefFromPointers<T>(begin, begin+size);
+}
+
+/*! \brief
+ * Constructs a reference to a particular range in a std::vector.
+ *
+ * \param[in] begin  Iterator to the beginning of a range.
+ * \param[in] end    Iterator to the end of a range.
+ *
+ * The referenced vector must remain valid and not be reallocated for
+ * the lifetime of this object.
+ *
+ * \related ArrayRef
+ */
+template <typename T>
+ArrayRef<T> arrayRefFromVector(typename std::vector<T>::iterator begin,
+                               typename std::vector<T>::iterator end)
+{
+    T * p_begin = (begin != end) ? &*begin : NULL;
+    T * p_end   = p_begin + (end-begin);
+    return arrayRefFromPointers<T>(p_begin, p_end);
+}
+
+
+
+/*! \brief
+ * STL-like container for non-mutable interface to a C array (or part of a
+ * std::vector).
  *
  * \tparam T  Value type of elements.
  *
@@ -75,6 +332,9 @@ namespace gmx
  *
  * Methods in this class do not throw, except where indicated.
  *
+ * Note that due to a Doxygen limitation, the constructor that takes a C array
+ * whose size is known at compile time does not appear in the documentation.
+ *
  * \inpublicapi
  * \ingroup module_utility
  */
@@ -109,6 +369,14 @@ class ConstArrayRef
          * Constructs an empty reference.
          */
         ConstArrayRef() : begin_(NULL), end_(NULL) {}
+        /*! \brief
+         * Constructs an empty reference.
+         *
+         * This is provided for convenience, such that EmptyArrayRef can be
+         * used to initialize any Const ArrayRef, without specifying the
+         * template type.  It is not explicit to enable that usage.
+         */
+        ConstArrayRef(const EmptyArrayRef &) : begin_(NULL), end_(NULL) {}
         /*! \brief
          * Constructs a reference to a particular range.
          *
@@ -116,49 +384,46 @@ class ConstArrayRef
          * \param[in] end    Pointer to the end of a range.
          *
          * Passed pointers must remain valid for the lifetime of this object.
+         *
+         * \note For clarity, use the non-member function constArrayRefFromPointers
+         * instead.
          */
         ConstArrayRef(const_pointer begin, const_pointer end)
             : begin_(begin), end_(end)
         {
             GMX_ASSERT(end >= begin, "Invalid range");
         }
+        //! \cond
+        // Doxygen 1.8.5 doesn't parse the declaration correctly...
         /*! \brief
-         * Constructs a reference to a particular range in a std::vector.
+         * Constructs a reference to a C array.
          *
-         * \param[in] begin  Iterator to the beginning of a range.
-         * \param[in] end    Iterator to the end of a range.
+         * \param[in] array  C array to reference.
+         * \tparam    count  Deduced number of elements in \p array.
          *
-         * The referenced vector must remain valid and not be reallocated for
-         * the lifetime of this object.
-         */
-        ConstArrayRef(typename std::vector<T>::const_iterator begin,
-                      typename std::vector<T>::const_iterator end)
-            : begin_((begin != end) ? &*begin : NULL),
-              end_(begin_+(end-begin))
-        {
-            GMX_ASSERT(end >= begin, "Invalid range");
-        }
-        /*! \brief
-         * Constructs a reference to an array.
+         * This constructor can only be used with a real array (not with a
+         * pointer).  It constructs a reference to the whole array, without
+         * a need to pass the number of elements explicitly.  The compiler
+         * must be able to deduce the array size.
+         * Passed array must remain valid for the lifetime of this object.
          *
-         * \param[in] begin  Pointer to the beginning of the array.
-         *      May be NULL if \p size is zero.
-         * \param[in] size   Number of elements in the array.
-         *
-         * Passed pointer must remain valid for the lifetime of this object.
+         * This constructor is not explicit to allow directly passing
+         * a C array to a function that takes a ConstArrayRef parameter.
          */
-        ConstArrayRef(const_pointer begin, size_type size)
-            : begin_(begin), end_(begin + size)
+        template <size_t count>
+        ConstArrayRef(const value_type (&array)[count])
+            : begin_(array), end_(array + count)
         {
         }
+        //! \endcond
 
-        //! Returns an interator to the beginning of the container.
+        //! Returns an iterator to the beginning of the container.
         const_iterator begin() const { return begin_; }
-        //! Returns an interator to the end of the container.
+        //! Returns an iterator to the end of the container.
         const_iterator end() const { return end_; }
-        //! Returns an interator to the reverse beginning of the container.
+        //! Returns an iterator to the reverse beginning of the container.
         const_iterator rbegin() const { return reverse_iterator(end()); }
-        //! Returns an interator to the reverse end of the container.
+        //! Returns an iterator to the reverse end of the container.
         const_iterator rend() const { return reverse_iterator(begin()); }
 
         //! Returns the size of the container.
@@ -204,6 +469,73 @@ class ConstArrayRef
         const_pointer           end_;
 };
 
+
+/*! \brief
+ * Constructs a reference to a particular range from two pointers.
+ *
+ * \param[in] begin  Pointer to the beginning of a range.
+ * \param[in] end    Pointer to the end of a range.
+ *
+ * Passed pointers must remain valid for the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromPointers(const T * begin, const T * end)
+{
+    return ConstArrayRef<T>(begin, end);
+}
+
+/*! \brief
+ * Constructs a reference to an array.
+ *
+ * \param[in] begin  Pointer to the beginning of the array.
+ *                   May be NULL if \p size is zero.
+ * \param[in] size   Number of elements in the array.
+ *
+ * Passed pointer must remain valid for the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromArray(const T * begin, size_t size)
+{
+    return constArrayRefFromPointers<T>(begin, begin+size);
+}
+
+/*! \brief
+ * Constructs a reference to a particular range in a std::vector.
+ *
+ * \param[in] begin  Iterator to the beginning of a range.
+ * \param[in] end    Iterator to the end of a range.
+ *
+ * The referenced vector must remain valid and not be reallocated for
+ * the lifetime of this object.
+ *
+ * \related ConstArrayRef
+ */
+template <typename T>
+ConstArrayRef<T> constArrayRefFromVector(typename std::vector<T>::const_iterator begin,
+                                         typename std::vector<T>::const_iterator end)
+{
+    const T * p_begin = (begin != end) ? &*begin : NULL;
+    const T * p_end   = p_begin + (end-begin);
+    return constArrayRefFromPointers<T>(p_begin, p_end);
+}
+
+/*! \brief
+ * Simple swap method for ArrayRef objects.
+ *
+ * \see ArrayRef::swap()
+ *
+ * \ingroup module_utility
+ */
+template <typename T>
+void swap(ArrayRef<T> &a, ArrayRef<T> &b)
+{
+    a.swap(b);
+}
+
 /*! \brief
  * Simple swap method for ConstArrayRef objects.
  *