"Fossies" - the Fresh Open Source Software Archive

Member "dune-typetree-2.8.0/dune/typetree/childextraction.hh" (31 Aug 2021, 10642 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "childextraction.hh" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.8.0_vs_2.9.0.

    1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    2 // vi: set et ts=8 sw=2 sts=2:
    3 
    4 #ifndef DUNE_TYPETREE_CHILDEXTRACTION_HH
    5 #define DUNE_TYPETREE_CHILDEXTRACTION_HH
    6 
    7 #include <type_traits>
    8 #include <utility>
    9 
   10 #include <dune/common/concept.hh>
   11 #include <dune/common/documentation.hh>
   12 #include <dune/common/typetraits.hh>
   13 #include <dune/common/shared_ptr.hh>
   14 
   15 #include <dune/typetree/nodeinterface.hh>
   16 #include <dune/typetree/treepath.hh>
   17 
   18 
   19 namespace Dune {
   20   namespace TypeTree {
   21 
   22     //! \addtogroup TypeTreeChildExtraction Child Extraction
   23     //! Utility functions and metafunctions for extracting children from a TypeTree.
   24     //! \ingroup TypeTree
   25     //! \{
   26 
   27 #ifndef DOXYGEN
   28 
   29     namespace Impl {
   30 
   31       // check at run time whether index is a valid child index
   32       template <class Node, class Index>
   33       std::true_type checkChildIndex (Node const& node, Index i)
   34       {
   35         assert(std::size_t(i) < node.degree() && "Child index out of range");
   36         return {};
   37       }
   38 
   39       // check at compile time whether index is a valid index
   40       template <class Node, std::size_t i>
   41       std::bool_constant<(i < Node::degree())> checkChildIndex (Node const& node, index_constant<i>)
   42       {
   43         static_assert(i < Node::degree(), "Child index out of range");
   44         return {};
   45       }
   46 
   47       // finally return the node itself if no further indices are provided. Break condition
   48       // for the recursion over the node childs.
   49       template<class Node>
   50       decltype(auto) childImpl (Node&& node)
   51       {
   52         return std::forward<Node>(node);
   53       }
   54 
   55       template<class NodePtr>
   56       auto childStorageImpl (NodePtr&& nodePtr)
   57       {
   58         return std::forward<NodePtr>(nodePtr);
   59       }
   60 
   61       // recursively call `node.child(...)` with the given indices
   62       template<class Node, class I0, class... I>
   63       decltype(auto) childImpl (Node&& node, I0 i0, I... i)
   64       {
   65         auto valid = checkChildIndex(node,i0);
   66         if constexpr (valid)
   67           return childImpl(node.child(i0),i...);
   68         else
   69           return;
   70       }
   71 
   72       // recursively call `node.childStorage(...)` with the given indices
   73       template<class NodePtr, class I0, class... I>
   74       decltype(auto) childStorageImpl (NodePtr&& nodePtr, I0 i0, I... i)
   75       {
   76         auto valid = checkChildIndex(*nodePtr,i0);
   77         if constexpr (valid)
   78           return childStorageImpl(nodePtr->childStorage(i0),i...);
   79         else
   80           return;
   81       }
   82 
   83       // forward to the impl methods by extracting the indices from the treepath
   84       template<class Node, class... Indices, std::size_t... i>
   85       decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
   86       {
   87         return childImpl(std::forward<Node>(node),treePathEntry<i>(tp)...);
   88       }
   89 
   90       // forward to the impl methods by extracting the indices from the treepath
   91       template<class NodePtr, class... Indices, std::size_t... i>
   92       decltype(auto) childStorage (NodePtr&& nodePtr, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
   93       {
   94         return childStorageImpl(std::forward<NodePtr>(nodePtr),treePathEntry<i>(tp)...);
   95       }
   96 
   97     } // end namespace Impl
   98 
   99 #endif // DOXYGEN
  100 
  101     //! Extracts the child of a node given by a sequence of compile-time and run-time indices.
  102     /**
  103      * Use this function to extract a (possibly indirect) child of a TypeTree node.
  104      *
  105      * Example:
  106      *
  107      * \code{.cc}
  108      * using namespace Dune::Indices;   // for compile-time indices
  109      * auto&& c = child(node,_4,2,_0,1);
  110      * \endcode
  111      *
  112      * returns the second child of the first child of the third child
  113      * of the fifth child of node, where some child lookups were done using
  114      * a compile-time index and some using a run-time index.
  115      *
  116      * \param node        The node from which to extract the child.
  117      * \param indices...  A list of indices that describes the path into the tree to the
  118      *                    wanted child. These parameters can be a combination of run time indices
  119      *                    (for tree nodes that allow accessing their children using run time information,
  120      *                    like PowerNode) and instances of index_constant, which work for all types of inner
  121      *                    nodes.
  122      * \return            A reference to the child, its cv-qualification depends on the passed-in node.
  123      */
  124     template<typename Node, typename... Indices>
  125 #ifdef DOXYGEN
  126     ImplementationDefined child (Node&& node, Indices... indices)
  127 #else
  128     decltype(auto) child (Node&& node, Indices... indices)
  129 #endif
  130     {
  131       return Impl::childImpl(std::forward<Node>(node),indices...);
  132     }
  133 
  134     template<typename Node, typename... Indices>
  135 #ifdef DOXYGEN
  136     ImplementationDefined childStorage (Node&& node, Indices... indices)
  137 #else
  138     auto childStorage (Node&& node, Indices... indices)
  139 #endif
  140     {
  141       static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices");
  142       return Impl::childStorageImpl(&node,indices...);
  143     }
  144 
  145     //! Extracts the child of a node given by a HybridTreePath object.
  146     /**
  147      * Use this function to extract a (possibly indirect) child of a TypeTree node.
  148      *
  149      * Example:
  150      *
  151      * \code{.cc}
  152      * using namespace Dune::TypeTree::Indices; // for compile-time indices
  153      * auto tp = Dune::TypeTree::hybridTreePath(_4,2,_0,1);
  154      * auto&& c = child(node,tp);
  155      * \endcode
  156      *
  157      * returns the second child of the first child of the third child
  158      * of the fifth child of node, where some child lookups were done using
  159      * a compile-time index and some using a run-time index.
  160      *
  161      * \param node        The node from which to extract the child.
  162      * \param tree{ath    A HybridTreePath that describes the path into the tree to the
  163      *                    wanted child. This tree path object  can be a combination of run time indices
  164      *                    (for tree nodes that allow accessing their children using run time information,
  165      *                    like PowerNode) and instances of index_constant, which work for all types of inner
  166      *                    nodes.
  167      * \return            A reference to the child, its cv-qualification depends on the passed-in node.
  168      */
  169     template<typename Node, typename... Indices>
  170 #ifdef DOXYGEN
  171     ImplementationDefined child (Node&& node, HybridTreePath<Indices...> treePath)
  172 #else
  173     decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp)
  174 #endif
  175     {
  176       return Impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
  177     }
  178 
  179     template<typename Node, typename... Indices>
  180 #ifdef DOXYGEN
  181     ImplementationDefined child (Node&& node, HybridTreePath<Indices...> treePath)
  182 #else
  183     auto childStorage (Node&& node, HybridTreePath<Indices...> tp)
  184 #endif
  185     {
  186       static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
  187       return Impl::childStorage(&node,tp,std::index_sequence_for<Indices...>{});
  188     }
  189 
  190 
  191 #ifndef DOXYGEN
  192 
  193     namespace impl {
  194 
  195       template<typename T>
  196       struct filter_void
  197       {
  198         using type = T;
  199       };
  200 
  201       template<>
  202       struct filter_void<void>
  203       {};
  204 
  205       template<typename Node, std::size_t... indices>
  206       struct _Child
  207         : public filter_void<std::decay_t<decltype(child(std::declval<Node>(),index_constant<indices>{}...))>>
  208       {};
  209 
  210     }
  211 
  212 #endif // DOXYGEN
  213 
  214     //! Template alias for the type of a child node given by a list of child indices.
  215     /**
  216      * This template alias is implemented in terms of the free-standing child() functions and uses those
  217      * in combination with decltype() to extract the child type.
  218 
  219      * \tparam Node     The type of the parent node.
  220      * \tparam indices  A list of index values the describes the path to the wanted child.
  221      */
  222     template<typename Node, std::size_t... indices>
  223     using Child = typename impl::_Child<Node,indices...>::type;
  224 
  225 
  226 #ifndef DOXYGEN
  227 
  228     namespace impl {
  229 
  230       template<typename Node, typename TreePath>
  231       struct _ChildForTreePath
  232       {
  233         using type = typename std::decay<decltype(child(std::declval<Node>(),std::declval<TreePath>()))>::type;
  234       };
  235 
  236     }
  237 
  238 #endif // DOXYGEN
  239 
  240     //! Template alias for the type of a child node given by a TreePath or a HybridTreePath type.
  241     /**
  242      * This template alias is implemented in terms of the free-standing child() functions and uses those
  243      * in combination with decltype() to extract the child type. It supports both TreePath and
  244      * HybridTreePath.
  245      *
  246      * \tparam Node      The type of the parent node.
  247      * \tparam TreePath  The type of a TreePath or a HybridTreePath that describes the path to the wanted child.
  248      */
  249     template<typename Node, typename TreePath>
  250     using ChildForTreePath = typename impl::_ChildForTreePath<Node,TreePath>::type;
  251 
  252 
  253 #ifndef DOXYGEN
  254 
  255     namespace impl {
  256 
  257       // By default, types are flat indices if they are integral
  258       template<typename T>
  259       struct _is_flat_index
  260       {
  261         using type = std::is_integral<T>;
  262       };
  263 
  264       // And so is any index_constant
  265       template<std::size_t i>
  266       struct _is_flat_index<index_constant<i>>
  267       {
  268         using type = std::true_type;
  269       };
  270 
  271     }
  272 
  273 #endif // DOXYGEN
  274 
  275     //! Type trait that determines whether T is a flat index in the context of child extraction.
  276     /*
  277      * This type trait can be used to check whether T is a flat index (i.e. either `std::size_t`
  278      * or `index_constant`). The type trait normalizes T before doing the check, so it will also
  279      * work correctly for references and cv-qualified types.
  280      */
  281     template<typename T>
  282     using is_flat_index = typename impl::_is_flat_index<std::decay_t<T>>::type;
  283 
  284 #ifndef DOXYGEN
  285 
  286     namespace impl {
  287 
  288       // helper function for check in member child() functions that tolerates being passed something that
  289       // isn't a TreePath. It will just return 0 in that case
  290 
  291       template<typename T>
  292       constexpr typename std::enable_if<
  293         Dune::TypeTree::is_flat_index<T>::value,
  294         bool
  295         >::type
  296       _non_empty_tree_path (T)
  297       {
  298         return false;
  299       }
  300 
  301       template<typename T>
  302       constexpr typename std::enable_if<
  303         !Dune::TypeTree::is_flat_index<T>::value,
  304         bool
  305         >::type
  306       _non_empty_tree_path (T t)
  307       {
  308         return treePathSize(t) > 0;
  309       }
  310 
  311     }
  312 
  313 #endif // DOXYGEN
  314 
  315     //! \} group TypeTree
  316 
  317   } // namespace TypeTree
  318 } //namespace Dune
  319 
  320 #endif // DUNE_TYPETREE_CHILDEXTRACTION_HH