]> https://gitweb.dealii.org/ - dealii.git/commitdiff
hp::Collection: allow range-based loop 12893/head
authorPeter Munch <peterrmuench@gmail.com>
Wed, 27 Oct 2021 18:45:39 +0000 (20:45 +0200)
committerPeter Munch <peterrmuench@gmail.com>
Wed, 27 Oct 2021 20:07:22 +0000 (22:07 +0200)
doc/news/changes/minor/20210027Munch [new file with mode: 0644]
include/deal.II/hp/collection.h
tests/hp/collection_iterator_01.cc [new file with mode: 0644]
tests/hp/collection_iterator_01.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20210027Munch b/doc/news/changes/minor/20210027Munch
new file mode 100644 (file)
index 0000000..8a138f3
--- /dev/null
@@ -0,0 +1,4 @@
+New: You can now perform range-based iterations on hp::FECollecion, hp::QCollection,
+and hp::MappingCollection objects.
+<br>
+(Peter Munch, 2021/10/27)
index 3c1c3ef17e1d125b8345e9f651839f76b0d7e091..ebce43e177ca76b6fd276a345f983d2efe318e5f 100644 (file)
@@ -28,6 +28,140 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace hp
 {
+  /**
+   * An iterator for hp::Collection.
+   */
+  template <typename T>
+  class CollectionIterator
+  {
+  public:
+    /**
+     * Constructor.
+     *
+     * @param data The actual data of hp::Collection.
+     * @param index The current index.
+     */
+    CollectionIterator(const std::vector<std::shared_ptr<const T>> &data,
+                       const std::size_t                            index)
+      : data(&data)
+      , index(index)
+    {}
+
+    /**
+     * Compare for equality.
+     */
+    bool
+    operator==(const CollectionIterator<T> &other) const
+    {
+      Assert(
+        this->data == other.data,
+        ExcMessage(
+          "You are trying to compare iterators into different hp::Collection objects."));
+      return this->index == other.index;
+    }
+
+    /**
+     * Compare for inequality.
+     */
+    bool
+    operator!=(const CollectionIterator<T> &other) const
+    {
+      Assert(
+        this->data == other.data,
+        ExcMessage(
+          "You are trying to compare iterators into different hp::Collection objects."));
+      return this->index != other.index;
+    }
+
+    /**
+     * Copy assignment.
+     */
+    CollectionIterator<T> &
+    operator=(const CollectionIterator<T> &other) = default;
+
+    /**
+     * Dereferencing operator: returns the value of the current index.
+     */
+    const T &
+    operator*() const
+    {
+      AssertIndexRange(index, data->size());
+      return *(*data)[index];
+    }
+
+    /**
+     * Prefix <tt>++</tt> operator: <tt>++iterator</tt>. This operator advances
+     * the iterator to the next index and returns a reference to
+     * <tt>*this</tt>.
+     */
+    CollectionIterator<T> &
+    operator++()
+    {
+      AssertIndexRange(index + 1, data->size() + 1);
+      index++;
+      return *this;
+    }
+
+    /**
+     * This operator advances the iterator by @p offset and returns a
+     * reference to <tt>*this</tt>.
+     */
+    CollectionIterator<T> &
+    operator+=(const std::size_t offset)
+    {
+      AssertIndexRange(index + offset, data->size() + 1);
+      index += offset;
+      return *this;
+    }
+
+    /**
+     * Prefix <tt>--</tt> operator: <tt>--iterator</tt>. This operator advances
+     * the iterator to the previous index and returns a reference to
+     * <tt>*this</tt>.
+     */
+    CollectionIterator<T> &
+    operator--()
+    {
+      Assert(
+        index > 0,
+        ExcMessage(
+          "You can't decrement an iterator that is already at the beginning of the range."));
+      --index;
+      return *this;
+    }
+
+    /**
+     * Create new iterator, which is shifted by @p offset.
+     */
+    CollectionIterator<T>
+    operator+(const std::size_t &offset) const
+    {
+      AssertIndexRange(index + offset, T::size() + 1);
+      return CollectionIterator<T>(*data, index + offset);
+    }
+
+    /**
+     * Compute distance between this iterator and iterator @p other.
+     */
+    std::ptrdiff_t
+    operator-(const CollectionIterator<T> &other) const
+    {
+      return static_cast<std::ptrdiff_t>(index) -
+             static_cast<ptrdiff_t>(other.index);
+    }
+
+  private:
+    /**
+     * Pointer to the actual data of hp::Collection.
+     */
+    const std::vector<std::shared_ptr<const T>> *data;
+
+    /**
+     * Current index.
+     */
+    std::size_t index;
+  };
+
   /**
    * This class implements a collection of objects.
    *
@@ -75,6 +209,20 @@ namespace hp
     std::size_t
     memory_consumption() const;
 
+    /**
+     * @return An iterator pointing to the beginning of the underlying data (`const`
+     * version).
+     */
+    CollectionIterator<T>
+    begin() const;
+
+    /**
+     * @return An iterator pointing to the end of the underlying data (`const`
+     * version).
+     */
+    CollectionIterator<T>
+    end() const;
+
   private:
     /**
      * The real container, which stores pointers to the different objects.
@@ -122,6 +270,24 @@ namespace hp
     return *entries[index];
   }
 
+
+
+  template <typename T>
+  CollectionIterator<T>
+  Collection<T>::begin() const
+  {
+    return CollectionIterator<T>(entries, 0);
+  }
+
+
+
+  template <typename T>
+  CollectionIterator<T>
+  Collection<T>::end() const
+  {
+    return CollectionIterator<T>(entries, entries.size());
+  }
+
 } // namespace hp
 
 
diff --git a/tests/hp/collection_iterator_01.cc b/tests/hp/collection_iterator_01.cc
new file mode 100644 (file)
index 0000000..2fdff5c
--- /dev/null
@@ -0,0 +1,39 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2021 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// Loop over entries of FECollection.
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/hp/fe_collection.h>
+
+#include "../tests.h"
+
+int
+main()
+{
+  initlog();
+
+  const unsigned int dim = 2;
+
+  hp::FECollection<dim> collection(FE_Q<dim>(1), FE_Q<dim>(2), FE_Q<dim>(3));
+
+  for (const auto &fe : collection)
+    deallog << fe.n_dofs_per_cell() << std::endl;
+
+  return 0;
+}
diff --git a/tests/hp/collection_iterator_01.output b/tests/hp/collection_iterator_01.output
new file mode 100644 (file)
index 0000000..e974f84
--- /dev/null
@@ -0,0 +1,4 @@
+
+DEAL::4
+DEAL::9
+DEAL::16

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.