From 35e305937fb28ed8a8e0214f9fb689fdeb612161 Mon Sep 17 00:00:00 2001
From: AAAlvesJr <aalvesju@gmail.com>
Date: Fri, 4 Dec 2020 14:15:45 +0100
Subject: [PATCH] [refactory-2020] stack implementations: more cleaning up.
 Moving implemententations to inl. SecondaryView.hpp

---
 .../detail/framework/stack/CombinedStack.inl  | 131 +---
 .../detail/framework/stack/SecondaryView.inl  | 649 +++++-------------
 corsika/framework/stack/CombinedStack.hpp     |  48 +-
 corsika/framework/stack/SecondaryView.hpp     | 150 +---
 4 files changed, 247 insertions(+), 731 deletions(-)

diff --git a/corsika/detail/framework/stack/CombinedStack.inl b/corsika/detail/framework/stack/CombinedStack.inl
index f109f67ce..400684153 100644
--- a/corsika/detail/framework/stack/CombinedStack.inl
+++ b/corsika/detail/framework/stack/CombinedStack.inl
@@ -16,114 +16,56 @@
 
 namespace corsika {
 
-  /**
-   * CombinedParticleInterface can be used to combine the data of several StackData
-   * objects.
-   *
-   * You may combine two StackData object, see class CombinedStackImpl
-   * below, into one Stack, using a combined StackIterator (aka
-   * CombinedParticleInterface) interface class.
-   *
-   * This allows to add specific information to a given Stack, could
-   * be special information on a subset of entries
-   * (e.g. NuclearStackExtension) or also (multi) thinning weights for
-   * all particles.
-   *
-   * Many Stacks can be combined into more complex object.
-   *
-   * The two sub-stacks must both provide their independent
-   * ParticleInterface classes.
-   *
-   */
-  template <template <typename> typename TParticleInterfaceA,
-            template <typename> class TParticleInterfaceB, typename TStackIterator>
-  struct CombinedParticleInterface
-      : public TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> {
-
-    typedef CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB,
-                                      TStackIterator>
-        pi_c_type;
-    typedef TParticleInterfaceA<TStackIterator> pi_a_type;
-    typedef TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> pi_b_type;
-
-  protected:
-    using pi_b_type::getIndex;     // choose B, A would also work
-    using pi_b_type::getStackData; // choose B, A would also work
-
-  public:
-    /**
-     * @name wrapper for user functions
-     * @{
-     *
-     * In this set of functions we call the user-provide
-     * TParticleInterface setParticleData(...) methods, either with
-     * parent particle reference, or w/o.
-     *
-     * There is one implicit assumption here: if only one data tuple
-     * is provided for setParticleData, the data is passed on to
-     * TParticleInterfaceA and the TParticleInterfaceB is
-     * default-initialized. There are many occasions where this is the
-     * desired behaviour, e.g. for thinning etc.
-     *
-     */
-
+   template <template <typename> class TParticleInterfaceA,
+             template <typename> class TParticleInterfaceB, typename TStackIterator>
     template <typename... TArgs1>
-    void setParticleData(std::tuple<TArgs1...> const vA) {
+    void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(std::tuple<TArgs1...> const vA) {
       pi_a_type::setParticleData(vA);
       pi_b_type::setParticleData();
     }
+
+      template <template <typename> class TParticleInterfaceA,
+                template <typename> class TParticleInterfaceB, typename TStackIterator>
     template <typename... TArgs1, typename... TArgs2>
-    void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) {
+    void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) {
       pi_a_type::setParticleData(vA);
       pi_b_type::setParticleData(vB);
     }
 
+      template <template <typename> class TParticleInterfaceA,
+                template <typename> class TParticleInterfaceB, typename TStackIterator>
     template <typename... TArgs1>
-    void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) {
+    void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) {
       // static_assert(MT<I>::has_not, "error");
       pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack
       pi_b_type::setParticleData(static_cast<pi_b_type&>(p));     // addon stack
     }
+
+   template <template <typename> class TParticleInterfaceA,
+             template <typename> class TParticleInterfaceB,typename TStackIterator>
     template <typename... TArgs1, typename... TArgs2>
-    void setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA,
+    void CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA,
                          std::tuple<TArgs2...> const vB) {
 
       pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA);
       pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB);
     }
+
     ///@}
-    std::string as_string() const {
+   template <template <typename> class TParticleInterfaceA,
+             template <typename> class TParticleInterfaceB, typename TStackIterator>
+    std::string CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB, TStackIterator>::as_string() const {
       return fmt::format("[[{}][{}]]", pi_a_type::as_string(), pi_b_type::as_string());
     }
 
-    protected:
-  };
-
-  /**
-   * @class CombinedStackImpl
-   *
-   * Memory implementation of a combined data stack.
-   *
-   * The two stack data user objects Stack1Impl and Stack2Impl are
-   * merged into one consistent Stack container object providing
-   * access to the combined number of data entries.
-   */
-  template <typename Stack1Impl, typename Stack2Impl>
-  class CombinedStackImpl : public Stack1Impl, public Stack2Impl {
-
-  public:
-    void clear() {
+
+   template <typename Stack1Impl, typename Stack2Impl>
+    void CombinedStackImpl< Stack1Impl, Stack2Impl>::clear() {
       Stack1Impl::clear();
       Stack2Impl::clear();
     }
-
-    unsigned int getSize() const { return Stack1Impl::getSize(); }
-    unsigned int getCapacity() const { return Stack1Impl::getCapacity(); }
-
-    /**
-     *   Function to copy particle at location i1 in stack to i2
-     */
-    void copy(const unsigned int i1, const unsigned int i2) {
+   template <typename Stack1Impl, typename Stack2Impl>
+    void CombinedStackImpl< Stack1Impl, Stack2Impl>::copy(const unsigned int i1, const unsigned int i2) {
       if (i1 >= getSize() || i2 >= getSize()) {
         std::ostringstream err;
         err << "CombinedStack: trying to access data beyond size of stack!";
@@ -133,10 +75,8 @@ namespace corsika {
       Stack2Impl::copy(i1, i2);
     }
 
-    /**
-     *   Function to copy particle at location i2 in stack to i1
-     */
-    void swap(const unsigned int i1, const unsigned int i2) {
+   template <typename Stack1Impl, typename Stack2Impl>
+    void CombinedStackImpl< Stack1Impl, Stack2Impl>::swap(const unsigned int i1, const unsigned int i2) {
       if (i1 >= getSize() || i2 >= getSize()) {
         std::ostringstream err;
         err << "CombinedStack: trying to access data beyond size of stack!";
@@ -146,30 +86,17 @@ namespace corsika {
       Stack2Impl::swap(i1, i2);
     }
 
-    void incrementSize() {
+   template <typename Stack1Impl, typename Stack2Impl>
+    void CombinedStackImpl< Stack1Impl, Stack2Impl>::incrementSize() {
       Stack1Impl::incrementSize();
       Stack2Impl::incrementSize();
     }
 
-    void decrementSize() {
+   template <typename Stack1Impl, typename Stack2Impl>
+    void CombinedStackImpl< Stack1Impl, Stack2Impl>::decrementSize() {
       Stack1Impl::decrementSize();
       Stack2Impl::decrementSize();
     }
 
-  }; // end class CombinedStackImpl
-
-  /**
-   * Helper template alias `CombinedStack` to construct new combined
-   * stack from two stack data objects and a particle readout interface.
-   *
-   * Note that the Stack2Impl provides only /additional/ data to
-   * Stack1Impl. This is important (see above) since tuple data for
-   * initialization are forwarded to Stack1Impl (first).
-   */
-
-  template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI>
-  using CombinedStack = Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI>;
 
 } // namespace corsika
-
-//#include <corsika/detail/framework/stack/CombinedStack.inl>
diff --git a/corsika/detail/framework/stack/SecondaryView.inl b/corsika/detail/framework/stack/SecondaryView.inl
index 576f6406d..a21c8b2d0 100644
--- a/corsika/detail/framework/stack/SecondaryView.inl
+++ b/corsika/detail/framework/stack/SecondaryView.inl
@@ -14,521 +14,214 @@
 #include <vector>
 
 namespace corsika {
-
-  // forward-decl:
-  template <class T1, template <class> class T2>
-  class DefaultSecondaryProducer;
-
-  /**
-   * @class SecondaryView
-   *
-   * SecondaryView can only be constructed by giving a valid
-   * Projectile particle, following calls to addSecondary will
-   * populate the original Stack, but will be directly accessible via
-   * the SecondaryView, e.g.
-
-     This allows to write code like
-     \verbatim
-     auto projectileInput = mainStack.getNextParticle();
-     const unsigned int nMain = mainStack.getSize();
-     SecondaryView<StackData, ParticleInterface> mainStackView(projectileInput);
-     mainStackView.addSecondary(...data...);
-     mainStackView.addSecondary(...data...);
-     mainStackView.addSecondary(...data...);
-     mainStackView.addSecondary(...data...);
-     assert(mainStackView.getSize() == 4);
-     assert(mainStack.getSize() = nMain+4);
-     \endverbatim
-
-     All operations possible on a Stack object are also possible on a
-     SecondaryView object. This means you can add, delete, copy, swap,
-     iterate, etc.
-
-     *Further information about implementation (for developers):* All
-     data is stored in the original stack privided at construction
-     time. The secondary particle (view) indices are stored in an
-     extra std::vector of SecondaryView class 'indices_' referring to
-     the original stack slot indices. The index of the primary
-     projectle particle is also explicitly stored in
-     'projectile_index_'. StackIterator indices
-     'i = StackIterator::getIndex()' are referring to those numbers,
-     where 'i==0' refers to the 'projectile_index_', and
-     'StackIterator::getIndex()>0' to 'indices_[i-1]', see function
-     getIndexFromIterator.
-   */
-
-  template <typename TStackDataType, template <typename> typename TParticleInterface,
-            template <typename T1, template <class> class T2> class MSecondaryProducer =
-                DefaultSecondaryProducer>
-  class SecondaryView : public Stack<TStackDataType&, TParticleInterface>,
-                        public MSecondaryProducer<TStackDataType, TParticleInterface> {
-
-    typedef SecondaryView<TStackDataType, TParticleInterface, MSecondaryProducer>
-        view_type;
-    /**
-     * Helper type for inside this class
-     */
-    typedef Stack<TStackDataType&, TParticleInterface> inner_stack_reference_type;
-
-    /**
-     * @name We need this "value" types with non-reference TStackData for
-     * the constructor of the SecondaryView class
-     * @{
-     */
-    typedef Stack<TStackDataType, TParticleInterface> inner_stack_value_type;
-
-  public:
-
-    typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
-                                   TParticleInterface, inner_stack_value_type>
-        stack_value_iterator;
-
-    typedef ConstStackIteratorInterface<
-        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        inner_stack_value_type>
-        const_stack_value_iterator;
-    /// @}
-
-    typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
-                                   TParticleInterface, view_type> stack_view_iterator;
-
-    typedef ConstStackIteratorInterface<
-        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>
-        const_stack_view_iterator;
-
-    /**
-     * this is the full type of the declared TParticleInterface:
-     */
-    using ParticleType = stack_view_iterator;
-    using ParticleInterfaceType = typename stack_view_iterator::particle_interface_type;
-
-    /**
-     * This is not accessible, since we don't want to allow creating a
-     * new stack.
-     */
-
-    template <typename... TArgs>
-    SecondaryView(TArgs... args) = delete;
-    SecondaryView() = delete;
-
-    /**
-        SecondaryView can only be constructed passing it a valid
-        stack_view_iterator to another Stack object (here: lvalue)
-      **/
-    SecondaryView(stack_value_iterator& particle)
-        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
-        , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
-        , inner_stack_(particle.getStack())
-        , projectile_index_(particle.getIndex()) {
-      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&)");
-    }
-    /**
-       SecondaryView can only be constructed passing it a valid
-       stack_view_iterator to another Stack object (here: rvalue)
-     **/
-    SecondaryView(stack_value_iterator&& particle)
-        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
-        , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
-        , inner_stack_(particle.getStack())
-        , projectile_index_(particle.getIndex()) {
-      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&&)");
-    }
-    /**
-     * Also allow to create a new View from a Projectile (stack_view_iterator on View)
-     *
-     * Note, the view generated this way will be equivalent to the orignal view in
-     * terms of reference to the underlying data stack. It is not a "view to a view".
-     */
-    SecondaryView(view_type& view, stack_view_iterator& projectile)
-
-        : Stack<TStackDataType&, TParticleInterface>{view.getStackData()}
-        , MSecondaryProducer<TStackDataType, TParticleInterface>{stack_value_iterator{
-              view.inner_stack_, view.getIndexFromIterator(projectile.getIndex())}}
-        , inner_stack_{view.inner_stack_}
-        , projectile_index_{view.getIndexFromIterator(projectile.getIndex())} {
-      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(view, projectile)");
-    }
-
-    /**
-     * This returns the projectile/parent in the original Stack, where this
-     * SecondaryView is derived from. This projectile should not be
-     * used to modify the Stack!
-     */
-    stack_value_iterator parent()
-        const { // todo: check if this can't be Conststack_value_iterator
-      return stack_value_iterator(inner_stack_, projectile_index_);
-    }
-
-    /**
-     * This returns the projectile/parent in the original Stack, where this
-     * SecondaryView is derived from. This projectile should not be
-     * used to modify the Stack!
-     */
-    stack_value_iterator asNewParent() const {
-      return stack_value_iterator(inner_stack_, projectile_index_);
-    }
-
-    /**
-     * This return a projectile of this SecondaryView, which can be
-     * used to modify the SecondaryView
-     */
-    stack_view_iterator getProjectile() {
-      // NOTE: 0 is special marker here for PROJECTILE, see getIndexFromIterator
-      return stack_view_iterator(*this, 0);
-    }
-    /**
-     * Method to add a new secondary particle on this SecondaryView
-     */
-    template <typename... Args>
-    stack_view_iterator addSecondary(const Args... v) {
+/*
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::
+
+*/
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+template <typename... Args>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::addSecondary(const Args... v) {
       CORSIKA_LOG_TRACE("SecondaryView::addSecondary(Args&&)");
       stack_view_iterator proj = getProjectile(); // make this const
       return addSecondary(proj, v...);
     }
-    /**
-     * overwrite Stack::getSize to return actual number of secondaries
-     */
-    unsigned int getSize() const { return indices_.size(); }
 
-    unsigned int getEntries() const {
-      return getSize() - inner_stack_reference_type::getErased();
-    }
-
-    bool isEmpty() const { return getEntries() == 0; }
 
-    /**
-     * @name These are functions required by std containers and std loops
-     * The Stack-versions must be overwritten, since here we need the correct
-     * SecondaryView::getSize
-     * @{
-     */
-    // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see
-    // getIndexFromIterator
-    stack_view_iterator begin() {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::begin() {
+	 unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
 
-        if (!isErased(i)) break;
-      }
-      return stack_view_iterator(*this, i + 1);
+	        if (!isErased(i)) break;
+	      }
+	      return stack_view_iterator(*this, i + 1);
     }
 
-    auto end() { return stack_view_iterator(*this, getSize() + 1); }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::begin() const {
+	 unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
+	        if (!isErased(i)) break;
+	      }
 
-    auto last() {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return stack_view_iterator(*this, getSize() - 1 - i + 1);
+	      return const_stack_view_iterator(*this, i + 1);
     }
 
-    auto begin() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(i)) break;
-      }
 
-      return const_stack_view_iterator(*this, i + 1);
-    }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::cbegin() const {
+	 unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
+	        if (!isErased(i)) break;
+	      }
 
-    auto end() const { return const_stack_view_iterator(*this, getSize() + 1); }
-    auto last() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
+	      return const_stack_view_iterator(*this, i + 1);
     }
 
-    auto cbegin() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-
-        if (!isErased(i)) break;
-      }
-      return const_stack_view_iterator(*this, i + 1);
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last()  {
+	  unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
+	        if (!isErased(getSize() - 1 - i)) break;
+	      }
+	      return stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
 
-
-    auto cend() const { return const_stack_view_iterator(*this, getSize()); }
-
-    auto clast() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last() const  {
+	  unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
+	        if (!isErased(getSize() - 1 - i)) break;
+	      }
+	      return stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
 
-    stack_view_iterator at(unsigned int i) { return stack_view_iterator(*this, i); }
-
-    const_stack_view_iterator at(unsigned int i) const {
-      return const_stack_view_iterator(*this, i);
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::last() const  {
+	  unsigned int i = 0;
+	      for (; i < getSize(); ++i) {
+	        if (!isErased(getSize() - 1 - i)) break;
+	      }
+	      return stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
 
-    stack_view_iterator first() { return stack_view_iterator{*this, 0}; }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::const_stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::clast() const  {
+    unsigned int i = 0;
+    for (; i < getSize(); ++i) {
 
-    const_stack_view_iterator cfirst() const {
-      return const_stack_view_iterator{*this, 0};
+      if (!isErased(getSize() - 1 - i)) break;
     }
-    /// @}
-
-    void swap(stack_view_iterator a, stack_view_iterator b) {
-
-      CORSIKA_LOG_TRACE("View::swap");
-      inner_stack_.swap(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
+    return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
-    void copy(stack_view_iterator a, stack_view_iterator b) {
 
-      CORSIKA_LOG_TRACE("View::copy");
-      inner_stack_.copy(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
-    }
-    void copy(const_stack_view_iterator a, stack_view_iterator b) {
 
-      CORSIKA_LOG_TRACE("View::copy");
-      inner_stack_.copy(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
-    }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::swap(stack_view_iterator a, stack_view_iterator b) {
 
-    /**
-     * need overwrite Stack::Delete, since we want to call
-     * SecondaryView::DeleteLast
-     *
-     * The particle is deleted on the underlying (internal) stack. The
-     * local references in SecondaryView in indices_ must be fixed,
-     * too.  The approach is to a) check if the particle 'p' is at the
-     * very end of the internal stack, b) if not: move it there by
-     * copying the last particle to the current particle location, c)
-     * remove the last particle.
-     *
-     */
-    void erase(stack_view_iterator p) {
-
-      CORSIKA_LOG_TRACE("SecondaryView::Delete");
-      if (isEmpty()) { /*error*/
-        throw std::runtime_error("Stack, cannot delete entry since size is zero");
-      }
-      if (isErased(p.getIndex() - 1)) { /*error*/
-        throw std::runtime_error("Stack, cannot delete entry since already deleted");
-      }
-      inner_stack_.erase(getIndexFromIterator(p.getIndex()));
-      inner_stack_reference_type::nDeleted_++; // also count in SecondaryView
-    }
-
-    /**
-     * return next particle from stack, need to overwrtie Stack::getNextParticle to get
-     * right reference
-     */
-    stack_view_iterator getNextParticle() {
-      while (purgeLastIfDeleted()) {}
-      return last();
-    }
-
-    /**
-     * check if this particle was already deleted
-     *
-     * need to re-implement for SecondaryView since stack_view_iterator types are a bit
-     * different
-     */
-    bool isErased(const stack_view_iterator& p) const {
-      return isErased(p.getIndex() - 1);
-    }
-
-    bool isErased(const const_stack_view_iterator& p) const {
-      return isErased(p.getIndex() - 1);
-    }
-    /**
-     * delete this particle
-     */
-    bool isErased(const ParticleInterfaceType& p) const {
-      return isErased(p.getIterator());
+    CORSIKA_LOG_TRACE("View::swap");
+    inner_stack_.swap(getIndexFromIterator(a.getIndex()),
+                      getIndexFromIterator(b.getIndex()));
     }
 
-    bool isDeleted(const const_stack_view_iterator& p) const {
-      return isDeleted(p.getIndex() - 1);
-    }
-    /**
-     * Function to ultimatively remove the last entry from the stack,
-     * if it was marked as deleted before. If this is not the case,
-     * the function will just return false and do nothing.
-     */
-    bool purgeLastIfDeleted() {
-      CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted");
-      if (!isErased(getSize() - 1))
-        return false; // the last particle is not marked for deletion. Do nothing.
-      inner_stack_.purge(getIndexFromIterator(getSize()));
-      inner_stack_reference_type::nDeleted_--;
-      indices_.pop_back();
-      return true;
-    }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::copy(stack_view_iterator a, stack_view_iterator b) {
 
-    /**
-     * Function to ultimatively remove all entries from the stack
-     * marked as deleted.
-     *
-     * Careful: this will re-order the entries on the stack, since
-     * "gaps" in the stack are filled with entries from the back
-     * (copied).
-     */
-    void purge() {
-      unsigned int iStack = 0;
-      unsigned int size = getSize();
-      while (iStack < size) {
-
-        if (isErased(iStack)) {
-          inner_stack_.purge(iStack);
-          indices_.erase(indices_.begin() + iStack);
-        }
-        size = getSize();
-        iStack++;
-      }
-      inner_stack_reference_type::nDeleted_ = 0;
-    }
 
-    std::string as_string() const {
-      std::string str(fmt::format("size {}\n", getSize()));
-      // we make our own begin/end since we want ALL entries
-      std::string new_line = "     ";
-      for (unsigned int iPart = 0; iPart != getSize(); ++iPart) {
-        const_stack_view_iterator itPart(*this, iPart);
-        str += fmt::format(
-            "{}{}{}", new_line, itPart.as_string(),
-            (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]"
-                                                                            : ""));
-        new_line = "\n     ";
-      }
-      return str;
-    }
+    CORSIKA_LOG_TRACE("View::copy");
+    inner_stack_.copy(getIndexFromIterator(a.getIndex()),
+                      getIndexFromIterator(b.getIndex()));
+    }
 
-  protected:
-
-    friend class StackIteratorInterface<
-        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>;
-
-    friend class ConstStackIteratorInterface<
-        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>;
-
-    friend class ParticleBase<stack_view_iterator>;
-
-    /**
-     * Overwrite of Stack::stack_view_iterator
-     *
-     * increase stack size, create new particle at end of stack,
-     * related to parent particle/projectile
-     *
-     * This should only get internally called from a
-     * stack_view_iterator::addSecondary via ParticleBase
-     */
-    template <typename... Args>
-    stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) {
-      CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)");
-      // make space on stack
-      inner_stack_reference_type::getStackData().incrementSize();
-      inner_stack_.deleted_.push_back(false);
-      // get current number of secondaries on stack
-      const unsigned int idSec = getSize();
-      // determine index on (inner) stack where new particle will be located
-      const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1;
-      indices_.push_back(index);
-      // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
-      // getIndexFromIterator
-      auto sec = stack_view_iterator(*this, idSec + 1, proj, v...);
-      MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec);
-      return sec;
-    }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::copy(const_stack_view_iterator a, stack_view_iterator b) {
 
-    // forward to inner stack
-    // this also checks the allowed bounds of 'i'
-    bool isErased(unsigned int i) const {
-      if (i >= indices_.size()) return false;
-      return inner_stack_.isErased(getIndexFromIterator(i + 1));
+	 CORSIKA_LOG_TRACE("View::copy");
+	      inner_stack_.copy(getIndexFromIterator(a.getIndex()),
+	                        getIndexFromIterator(b.getIndex()));
     }
 
-    /**
-     * We only want to 'see' secondaries indexed in indices_. In this
-     * function the conversion form iterator-index to stack-index is
-     * performed.
-     */
-    unsigned int getIndexFromIterator(const unsigned int vI) const {
-      // this is too much: CORSIKA_LOG_TRACE("SecondaryView::getIndexFromIterator({})={}",
-      // vI, (vI?indices_[vI-1]:projectile_index_));
-      if (vI == 0) return projectile_index_;
-      return indices_[vI - 1];
-    }
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::erase(stack_view_iterator p) {
 
-  private:
-    inner_stack_value_type& inner_stack_;
-    unsigned int projectile_index_;
-    std::vector<unsigned int> indices_;
-  };
-
-
-  /**
-   * Class to handle the generation of new secondaries. Used as default mix-in for
-   * SecondaryView.
-   */
-  template <class T1, template <class> class T2>
-  class DefaultSecondaryProducer {
-    using View = SecondaryView<T1, T2, DefaultSecondaryProducer>;
-
-  public:
-    static bool constexpr has_event{false};
-
-    /**
-     * Method is called after a new secondary has been created on the
-     * SecondaryView. Extra logic can be introduced here.
-     *
-     * The input Particle is the new secondary that was produced and
-     * is of course a reference into the SecondaryView itself.
-     */
-    template <typename Particle>
-    auto new_secondary(Particle&&) const {
-      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)");
-    }
+	 CORSIKA_LOG_TRACE("SecondaryView::Delete");
+	      if (isEmpty()) { /*error*/
+	        throw std::runtime_error("Stack, cannot delete entry since size is zero");
+	      }
+	      if (isErased(p.getIndex() - 1)) { /*error*/
+	        throw std::runtime_error("Stack, cannot delete entry since already deleted");
+	      }
+	      inner_stack_.erase(getIndexFromIterator(p.getIndex()));
+	      inner_stack_reference_type::nDeleted_++; // also count in SecondaryView
+    }
+
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+bool SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::purgeLastIfDeleted() {
+    CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted");
+    if (!isErased(getSize() - 1))
+      return false; // the last particle is not marked for deletion. Do nothing.
+    inner_stack_.purge(getIndexFromIterator(getSize()));
+    inner_stack_reference_type::nDeleted_--;
+    indices_.pop_back();
+    return true;
+  }
+
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+void SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::purge() {
+    unsigned int iStack = 0;
+    unsigned int size = getSize();
+    while (iStack < size) {
 
-    /**
-     * Method is called when a new SecondaryView is being created
-     * created. Extra logic can be introduced here.
-     *
-     * The input Particle is a reference object into the original
-     * parent stack! It is not a reference into the SecondaryView
-     * itself.
-     */
-    template <typename Particle>
-    DefaultSecondaryProducer(Particle const&) {
-
-      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)");
-    }
-  };
-
-  /*
-    See Issue 161
-
-    unfortunately clang does not support this in the same way (yet) as
-    gcc, so we have to distinguish here. If clang cataches up, we
-    could remove the #if here and elsewhere. The gcc code is much more
-    generic and universal.
-  */
-#if not defined(__clang__) && defined(__GNUC__) || defined(__GNUG__)
-  template <typename TStack,
-
-            template <class TStack_, template <class> class pi_type_>
-            class MSecondaryProducer = corsika::DefaultSecondaryProducer,
-            template <typename> typename pi_type_ = TStack::template pi_type>
-  struct MakeView {
-    using type = corsika::SecondaryView<typename TStack::stack_implementation_type,
-                                        pi_type_, MSecondaryProducer>;
-  };
-#endif
+      if (isErased(iStack)) {
+        inner_stack_.purge(iStack);
+        indices_.erase(indices_.begin() + iStack);
+      }
+      size = getSize();
+      iStack++;
+    }
+    inner_stack_reference_type::nDeleted_ = 0;
+  }
+
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+std::string SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::as_string() const {
+    std::string str(fmt::format("size {}\n", getSize()));
+    // we make our own begin/end since we want ALL entries
+    std::string new_line = "     ";
+    for (unsigned int iPart = 0; iPart != getSize(); ++iPart) {
+      const_stack_view_iterator itPart(*this, iPart);
+      str += fmt::format(
+          "{}{}{}", new_line, itPart.as_string(),
+          (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]"
+                                                                          : ""));
+      new_line = "\n     ";
+    }
+    return str;
+  }
+
+template <typename TStackDataType, template <typename> typename TParticleInterface,
+          template <typename T1, template <class> class T2> class MSecondaryProducer>
+template <typename... Args>
+typename SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::stack_view_iterator
+SecondaryView< TStackDataType,TParticleInterface, MSecondaryProducer>::addSecondary(stack_view_iterator& proj, const Args... v) {
+    CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)");
+    // make space on stack
+    inner_stack_reference_type::getStackData().incrementSize();
+    inner_stack_.deleted_.push_back(false);
+    // get current number of secondaries on stack
+    const unsigned int idSec = getSize();
+    // determine index on (inner) stack where new particle will be located
+    const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1;
+    indices_.push_back(index);
+    // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
+    // getIndexFromIterator
+    auto sec = stack_view_iterator(*this, idSec + 1, proj, v...);
+    MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec);
+    return sec;
+  }
 
 } // namespace corsika
-
-//#include <corsika/detail/framework/stack/SecondaryView.inl>
diff --git a/corsika/framework/stack/CombinedStack.hpp b/corsika/framework/stack/CombinedStack.hpp
index 0df3532f4..da77f01d1 100644
--- a/corsika/framework/stack/CombinedStack.hpp
+++ b/corsika/framework/stack/CombinedStack.hpp
@@ -67,34 +67,37 @@ namespace corsika {
      */
 
     template <typename... TArgs1>
-    void setParticleData(std::tuple<TArgs1...> const vA) {
+    void setParticleData(std::tuple<TArgs1...> const vA);
+    /* {
       pi_a_type::setParticleData(vA);
       pi_b_type::setParticleData();
-    }
+    }*/
+
     template <typename... TArgs1, typename... TArgs2>
-    void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) {
+    void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB); /*{
       pi_a_type::setParticleData(vA);
       pi_b_type::setParticleData(vB);
-    }
+    }*/
 
     template <typename... TArgs1>
-    void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) {
+    void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA);/* {
       // static_assert(MT<I>::has_not, "error");
       pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack
       pi_b_type::setParticleData(static_cast<pi_b_type&>(p));     // addon stack
-    }
+    }*/
+
     template <typename... TArgs1, typename... TArgs2>
     void setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA,
-                         std::tuple<TArgs2...> const vB) {
+                         std::tuple<TArgs2...> const vB);/* {
 
       pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA);
       pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB);
-    }
+    }*/
     ///@}
 
-    std::string as_string() const {
+    std::string as_string() const;/* {
       return fmt::format("[[{}][{}]]", pi_a_type::as_string(), pi_b_type::as_string());
-    }
+    }*/
 
   private:
   protected:
@@ -110,13 +113,14 @@ namespace corsika {
    * access to the combined number of data entries.
    */
   template <typename Stack1Impl, typename Stack2Impl>
-  class CombinedStackImpl : public Stack1Impl, public Stack2Impl {
+  struct CombinedStackImpl : public Stack1Impl, public Stack2Impl {
 
   public:
-    void clear() {
+
+    void clear();/* {
       Stack1Impl::clear();
       Stack2Impl::clear();
-    }
+    }*/
 
     unsigned int getSize() const { return Stack1Impl::getSize(); }
     unsigned int getCapacity() const { return Stack1Impl::getCapacity(); }
@@ -124,7 +128,7 @@ namespace corsika {
     /**
      *   Function to copy particle at location i1 in stack to i2
      */
-    void copy(const unsigned int i1, const unsigned int i2) {
+    void copy(const unsigned int i1, const unsigned int i2);/* {
       if (i1 >= getSize() || i2 >= getSize()) {
         std::ostringstream err;
         err << "CombinedStack: trying to access data beyond size of stack!";
@@ -132,12 +136,12 @@ namespace corsika {
       }
       Stack1Impl::copy(i1, i2);
       Stack2Impl::copy(i1, i2);
-    }
+    }*/
 
     /**
      *   Function to copy particle at location i2 in stack to i1
      */
-    void swap(const unsigned int i1, const unsigned int i2) {
+    void swap(const unsigned int i1, const unsigned int i2);/* {
       if (i1 >= getSize() || i2 >= getSize()) {
         std::ostringstream err;
         err << "CombinedStack: trying to access data beyond size of stack!";
@@ -145,17 +149,17 @@ namespace corsika {
       }
       Stack1Impl::swap(i1, i2);
       Stack2Impl::swap(i1, i2);
-    }
+    }*/
 
-    void incrementSize() {
+    void incrementSize();/* {
       Stack1Impl::incrementSize();
       Stack2Impl::incrementSize();
-    }
+    }*/
 
-    void decrementSize() {
+    void decrementSize();/* {
       Stack1Impl::decrementSize();
       Stack2Impl::decrementSize();
-    }
+    }*/
 
   }; // end class CombinedStackImpl
 
@@ -173,4 +177,4 @@ namespace corsika {
   
 } // namespace corsika
 
-//#include <corsika/detail/framework/stack/CombinedStack.inl>
+#include <corsika/detail/framework/stack/CombinedStack.inl>
diff --git a/corsika/framework/stack/SecondaryView.hpp b/corsika/framework/stack/SecondaryView.hpp
index 79abc168f..45369e0e9 100644
--- a/corsika/framework/stack/SecondaryView.hpp
+++ b/corsika/framework/stack/SecondaryView.hpp
@@ -200,11 +200,8 @@ namespace corsika {
      * Method to add a new secondary particle on this SecondaryView
      */
     template <typename... Args>
-    stack_view_iterator addSecondary(const Args... v) {
-      CORSIKA_LOG_TRACE("SecondaryView::addSecondary(Args&&)");
-      stack_view_iterator proj = getProjectile(); // make this const
-      return addSecondary(proj, v...);
-    }
+    stack_view_iterator addSecondary(const Args... v);
+
     /**
      * overwrite Stack::getSize to return actual number of secondaries
      */
@@ -224,60 +221,23 @@ namespace corsika {
      */
     // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see
     // getIndexFromIterator
-    stack_view_iterator begin() {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(i)) break;
-      }
-      return stack_view_iterator(*this, i + 1);
-    }
+    stack_view_iterator begin();
 
-    auto end() { return stack_view_iterator(*this, getSize() + 1); }
-
-    auto last() {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return stack_view_iterator(*this, getSize() - 1 - i + 1);
-    }
+    stack_view_iterator end() { return stack_view_iterator(*this, getSize() + 1); }
 
-    auto begin() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(i)) break;
-      }
+    stack_view_iterator last();
 
-      return const_stack_view_iterator(*this, i + 1);
-    }
+    const_stack_view_iterator begin() const ;
 
-    auto end() const { return const_stack_view_iterator(*this, getSize() + 1); }
+    const_stack_view_iterator end() const { return const_stack_view_iterator(*this, getSize() + 1); }
 
-    auto last() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
-    }
+    const_stack_view_iterator last() const;
 
-    auto cbegin() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(i)) break;
-      }
-      return const_stack_view_iterator(*this, i + 1);
-    }
+    const_stack_view_iterator cbegin() const;
 
     auto cend() const { return const_stack_view_iterator(*this, getSize()); }
 
-    auto clast() const {
-      unsigned int i = 0;
-      for (; i < getSize(); ++i) {
-        if (!isErased(getSize() - 1 - i)) break;
-      }
-      return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
-    }
+    const_stack_view_iterator clast() const;
 
     stack_view_iterator at(unsigned int i) { return stack_view_iterator(*this, i); }
 
@@ -292,21 +252,11 @@ namespace corsika {
     }
     /// @}
 
-    void swap(stack_view_iterator a, stack_view_iterator b) {
-      CORSIKA_LOG_TRACE("View::swap");
-      inner_stack_.swap(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
-    }
-    void copy(stack_view_iterator a, stack_view_iterator b) {
-      CORSIKA_LOG_TRACE("View::copy");
-      inner_stack_.copy(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
-    }
-    void copy(const_stack_view_iterator a, stack_view_iterator b) {
-      CORSIKA_LOG_TRACE("View::copy");
-      inner_stack_.copy(getIndexFromIterator(a.getIndex()),
-                        getIndexFromIterator(b.getIndex()));
-    }
+    void swap(stack_view_iterator a, stack_view_iterator b) ;
+
+    void copy(stack_view_iterator a, stack_view_iterator b);
+
+    void copy(const_stack_view_iterator a, stack_view_iterator b);
 
     /**
      * need overwrite Stack::Delete, since we want to call
@@ -320,17 +270,7 @@ namespace corsika {
      * remove the last particle.
      *
      */
-    void erase(stack_view_iterator p) {
-      CORSIKA_LOG_TRACE("SecondaryView::Delete");
-      if (isEmpty()) { /*error*/
-        throw std::runtime_error("Stack, cannot delete entry since size is zero");
-      }
-      if (isErased(p.getIndex() - 1)) { /*error*/
-        throw std::runtime_error("Stack, cannot delete entry since already deleted");
-      }
-      inner_stack_.erase(getIndexFromIterator(p.getIndex()));
-      inner_stack_reference_type::nDeleted_++; // also count in SecondaryView
-    }
+    void erase(stack_view_iterator p);
 
     /**
      * return next particle from stack, need to overwrtie Stack::getNextParticle to get
@@ -366,15 +306,7 @@ namespace corsika {
      * if it was marked as deleted before. If this is not the case,
      * the function will just return false and do nothing.
      */
-    bool purgeLastIfDeleted() {
-      CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted");
-      if (!isErased(getSize() - 1))
-        return false; // the last particle is not marked for deletion. Do nothing.
-      inner_stack_.purge(getIndexFromIterator(getSize()));
-      inner_stack_reference_type::nDeleted_--;
-      indices_.pop_back();
-      return true;
-    }
+    bool purgeLastIfDeleted();
 
     /**
      * Function to ultimatively remove all entries from the stack
@@ -384,34 +316,9 @@ namespace corsika {
      * "gaps" in the stack are filled with entries from the back
      * (copied).
      */
-    void purge() {
-      unsigned int iStack = 0;
-      unsigned int size = getSize();
-      while (iStack < size) {
-        if (isErased(iStack)) {
-          inner_stack_.purge(iStack);
-          indices_.erase(indices_.begin() + iStack);
-        }
-        size = getSize();
-        iStack++;
-      }
-      inner_stack_reference_type::nDeleted_ = 0;
-    }
+    void purge() ;
 
-    std::string as_string() const {
-      std::string str(fmt::format("size {}\n", getSize()));
-      // we make our own begin/end since we want ALL entries
-      std::string new_line = "     ";
-      for (unsigned int iPart = 0; iPart != getSize(); ++iPart) {
-        const_stack_view_iterator itPart(*this, iPart);
-        str += fmt::format(
-            "{}{}{}", new_line, itPart.as_string(),
-            (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]"
-                                                                            : ""));
-        new_line = "\n     ";
-      }
-      return str;
-    }
+    std::string as_string() const;
 
   protected:
     friend class StackIteratorInterface<
@@ -434,22 +341,7 @@ namespace corsika {
      * stack_view_iterator::addSecondary via ParticleBase
      */
     template <typename... Args>
-    stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) {
-      CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)");
-      // make space on stack
-      inner_stack_reference_type::getStackData().incrementSize();
-      inner_stack_.deleted_.push_back(false);
-      // get current number of secondaries on stack
-      const unsigned int idSec = getSize();
-      // determine index on (inner) stack where new particle will be located
-      const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1;
-      indices_.push_back(index);
-      // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
-      // getIndexFromIterator
-      auto sec = stack_view_iterator(*this, idSec + 1, proj, v...);
-      MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec);
-      return sec;
-    }
+    stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) ;
 
     // forward to inner stack
     // this also checks the allowed bounds of 'i'
@@ -534,4 +426,4 @@ namespace corsika {
 
 } // namespace corsika
 
-//#include <corsika/detail/framework/stack/SecondaryView.inl>
+#include <corsika/detail/framework/stack/SecondaryView.inl>
-- 
GitLab