"Fossies" - the Fresh Open Source Software Archive

Member "dune-typetree-2.8.0/dune/typetree/compositenode.hh" (31 Aug 2021, 7883 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 "compositenode.hh" see the Fossies "Dox" file reference documentation.

    1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    2 // vi: set et ts=4 sw=2 sts=2:
    3 
    4 #ifndef DUNE_TYPETREE_COMPOSITENODE_HH
    5 #define DUNE_TYPETREE_COMPOSITENODE_HH
    6 
    7 #include <tuple>
    8 #include <memory>
    9 #include <type_traits>
   10 
   11 #include <dune/typetree/nodetags.hh>
   12 #include <dune/typetree/childextraction.hh>
   13 #include <dune/typetree/typetraits.hh>
   14 
   15 namespace Dune {
   16   namespace TypeTree {
   17 
   18     /** \addtogroup Nodes
   19      *  \ingroup TypeTree
   20      *  \{
   21      */
   22 
   23     //! Base class for composite nodes based on variadic templates.
   24     template<typename... Children>
   25     class CompositeNode
   26     {
   27 
   28     public:
   29 
   30       //! The type tag that describes a CompositeNode.
   31       typedef CompositeNodeTag NodeTag;
   32 
   33       //! The type used for storing the children.
   34       typedef std::tuple<std::shared_ptr<Children>... > NodeStorage;
   35 
   36       //! A tuple storing the types of all children.
   37       typedef std::tuple<Children...> ChildTypes;
   38 
   39       //! Mark this class as non leaf in the \ref TypeTree.
   40       static const bool isLeaf = false;
   41 
   42       //! Mark this class as a non power in the \ref TypeTree.
   43       static const bool isPower = false;
   44 
   45       //! Mark this class as a composite in the \ref TypeTree.
   46       static const bool isComposite = true;
   47 
   48       //! The number of children.
   49       static const std::size_t CHILDREN = sizeof...(Children);
   50 
   51       static constexpr auto degree ()
   52       {
   53         return std::integral_constant<std::size_t,sizeof...(Children)>{};
   54       }
   55 
   56       //! Access to the type and storage type of the i-th child.
   57       template<std::size_t k>
   58       struct Child {
   59 
   60         static_assert((k < CHILDREN), "child index out of range");
   61 
   62         //! The type of the child.
   63         typedef typename std::tuple_element<k,ChildTypes>::type Type;
   64 
   65         //! The type of the child.
   66         typedef typename std::tuple_element<k,ChildTypes>::type type;
   67       };
   68 
   69       //! @name Child Access
   70       //! @{
   71 
   72       //! Returns the k-th child.
   73       /**
   74        * \returns a reference to the k-th child.
   75        */
   76       template<std::size_t k>
   77       typename Child<k>::Type& child (index_constant<k> = {})
   78       {
   79         return *std::get<k>(_children);
   80       }
   81 
   82       //! Returns the k-th child (const version).
   83       /**
   84        * \returns a const reference to the k-th child.
   85        */
   86       template<std::size_t k>
   87       const typename Child<k>::Type& child (index_constant<k> = {}) const
   88       {
   89         return *std::get<k>(_children);
   90       }
   91 
   92       //! Returns the storage of the k-th child.
   93       /**
   94        * \returns a copy of the object storing the k-th child.
   95        */
   96       template<std::size_t k>
   97       std::shared_ptr<typename Child<k>::Type> childStorage (index_constant<k> = {})
   98       {
   99         return std::get<k>(_children);
  100       }
  101 
  102       //! Returns the storage of the k-th child (const version).
  103       /**
  104        * \returns a copy of the object storing the k-th child.
  105        */
  106       template<std::size_t k>
  107       std::shared_ptr<const typename Child<k>::Type> childStorage (index_constant<k> = {}) const
  108       {
  109         return std::get<k>(_children);
  110       }
  111 
  112       //! Sets the k-th child to the passed-in value.
  113       template<std::size_t k>
  114       void setChild (typename Child<k>::Type& child, index_constant<k> = {})
  115       {
  116         std::get<k>(_children) = stackobject_to_shared_ptr(child);
  117       }
  118 
  119       //! Store the passed value in k-th child.
  120       template<std::size_t k>
  121       void setChild (typename Child<k>::Type&& child, index_constant<k> = {})
  122       {
  123         std::get<k>(_children) = convert_arg(std::move(child));
  124       }
  125 
  126       //! Sets the storage of the k-th child to the passed-in value.
  127       template<std::size_t k>
  128       void setChild (std::shared_ptr<typename Child<k>::Type> child, index_constant<k> = {})
  129       {
  130         std::get<k>(_children) = std::move(child);
  131       }
  132 
  133       const NodeStorage& nodeStorage () const
  134       {
  135         return _children;
  136       }
  137 
  138       //! @}
  139 
  140       //! @name Nested Child Access
  141       //! @{
  142 
  143       // The following two methods require a little bit of SFINAE trickery to work correctly:
  144       // We have to make sure that they don't shadow the methods for direct child access because
  145       // those get called by the generic child() machinery. If that machinery picks up the methods
  146       // defined below, we have an infinite recursion.
  147       // So the methods make sure that either
  148       //
  149       // * there are more than one argument. In that case, we got multiple indices and can forward
  150       //   to the general machine.
  151       //
  152       // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
  153       //   The argument thus has to be some kind of TreePath instance that we can also pass to the
  154       //   generic machine.
  155       //
  156       // The above SFINAE logic works, but there is still a problem with the return type deduction.
  157       // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
  158       // type deduction will trigger the infinite recursion.
  159 
  160       //! Returns the child given by the list of indices.
  161       /**
  162        * This method simply forwards to the freestanding function child(). See that
  163        * function for further information.
  164        */
  165 #ifdef DOXYGEN
  166       template<typename... Indices>
  167       ImplementationDefined& child (Indices... indices)
  168 #else
  169       template<typename I0, typename... I,
  170         std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
  171       decltype(auto) child (I0 i0, I... i)
  172 #endif
  173       {
  174         static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
  175           "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
  176           );
  177         return Dune::TypeTree::child(*this,i0,i...);
  178       }
  179 
  180       //! Returns the child given by the list of indices.
  181       /**
  182        * This method simply forwards to the freestanding function child(). See that
  183        * function for further information.
  184        */
  185 #ifdef DOXYGEN
  186       template<typename... Indices>
  187       const ImplementationDefined& child (Indices... indices)
  188 #else
  189       template<typename I0, typename... I,
  190         std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
  191       decltype(auto) child (I0 i0, I... i) const
  192 #endif
  193       {
  194         static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
  195           "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
  196           );
  197         return Dune::TypeTree::child(*this,i0,i...);
  198       }
  199 
  200       //! @}
  201 
  202     protected:
  203 
  204       //! @name Constructors
  205       //! @{
  206 
  207       //! Default constructor.
  208       /**
  209        * This constructor requires the storage type to be default
  210        * constructible.
  211        * \warning If the storage type is a pointer, the resulting object
  212        * will not be usable before its children are set using any of the
  213        * setChild(...) methods!
  214        */
  215       CompositeNode ()
  216       {}
  217 
  218       //! Initialize all children with the passed-in objects.
  219       template<typename... Args, typename = typename std::enable_if<(sizeof...(Args) == CHILDREN)>::type>
  220       CompositeNode (Args&&... args)
  221         : _children(convert_arg(std::forward<Args>(args))...)
  222       {}
  223 
  224       //! Initialize the CompositeNode with copies of the passed in Storage objects.
  225       CompositeNode (std::shared_ptr<Children>... children)
  226         : _children(std::move(children)...)
  227       {}
  228 
  229       //! Initialize the CompositeNode with a copy of the passed-in storage type.
  230       CompositeNode (const NodeStorage& children)
  231         : _children(children)
  232       {}
  233 
  234       //! @}
  235 
  236     private:
  237       NodeStorage _children;
  238     };
  239 
  240     //! \} group Nodes
  241 
  242   } // namespace TypeTree
  243 } //namespace Dune
  244 
  245 #endif // DUNE_TYPETREE_COMPOSITENODE_HH