"Fossies" - the Fresh Open Source Software Archive

Member "dune-typetree-2.8.0/dune/typetree/powernode.hh" (31 Aug 2021, 11649 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 "powernode.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_POWERNODE_HH
    5 #define DUNE_TYPETREE_POWERNODE_HH
    6 
    7 #include <cassert>
    8 #include <array>
    9 #include <memory>
   10 #include <type_traits>
   11 
   12 #include <dune/common/typetraits.hh>
   13 #include <dune/common/std/type_traits.hh>
   14 
   15 #include <dune/typetree/nodetags.hh>
   16 #include <dune/typetree/utility.hh>
   17 #include <dune/typetree/childextraction.hh>
   18 #include <dune/typetree/typetraits.hh>
   19 
   20 namespace Dune {
   21   namespace TypeTree {
   22 
   23     /** \addtogroup Nodes
   24      *  \ingroup TypeTree
   25      *  \{
   26      */
   27 
   28 
   29 #ifndef DOXYGEN
   30 
   31     //! Helper struct to make constructor enabling mechanism in PowerNode more readable.
   32     template<typename PowerNode, typename T, std::size_t k>
   33     struct AssertPowerNodeChildCount
   34       : public std::enable_if<std::is_same<
   35                            typename PowerNode::ChildType,
   36                            T>::value &&
   37     PowerNode::CHILDREN == k,
   38                          T>
   39     {};
   40 
   41 #endif
   42 
   43     /** \brief Collect k instances of type T within a \ref TypeTree.
   44      *
   45      *  \tparam T The base type
   46      *  \tparam k The number of instances this node should collect
   47      */
   48     template<typename T, std::size_t k>
   49     class PowerNode
   50     {
   51 
   52     public:
   53 
   54       //! Mark this class as non leaf in the \ref TypeTree.
   55       static const bool isLeaf = false;
   56 
   57       //! Mark this class as a power in the \ref TypeTree.
   58       static const bool isPower = true;
   59 
   60       //! Mark this class as a non composite in the \ref TypeTree.
   61       static const bool isComposite = false;
   62 
   63       //! The number of children.
   64       static const std::size_t CHILDREN = k;
   65 
   66       static constexpr auto degree ()
   67       {
   68         return std::integral_constant<std::size_t,k>{};
   69       }
   70 
   71       //! The type tag that describes a PowerNode.
   72       typedef PowerNodeTag NodeTag;
   73 
   74       //! The type of each child.
   75       typedef T ChildType;
   76 
   77       //! The type used for storing the children.
   78       typedef std::array<std::shared_ptr<T>,k> NodeStorage;
   79 
   80 
   81       //! Access to the type and storage type of the i-th child.
   82       template<std::size_t i>
   83       struct Child
   84       {
   85 
   86         static_assert((i < CHILDREN), "child index out of range");
   87 
   88         //! The type of the child.
   89         typedef T Type;
   90 
   91         //! The type of the child.
   92         typedef T type;
   93       };
   94 
   95       //! @name Child Access (templated methods)
   96       //! @{
   97 
   98       //! Returns the i-th child.
   99       /**
  100        * \returns a reference to the i-th child.
  101        */
  102       template<std::size_t i>
  103       T& child (index_constant<i> = {})
  104       {
  105         static_assert((i < CHILDREN), "child index out of range");
  106         return *_children[i];
  107       }
  108 
  109       //! Returns the i-th child (const version).
  110       /**
  111        * \returns a const reference to the i-th child.
  112        */
  113       template<std::size_t i>
  114       const T& child (index_constant<i> = {}) const
  115       {
  116         static_assert((i < CHILDREN), "child index out of range");
  117         return *_children[i];
  118       }
  119 
  120       //! Returns the storage of the i-th child.
  121       /**
  122        * \returns a copy of the object storing the i-th child.
  123        */
  124       template<std::size_t i>
  125       std::shared_ptr<T> childStorage (index_constant<i> = {})
  126       {
  127         static_assert((i < CHILDREN), "child index out of range");
  128         return _children[i];
  129       }
  130 
  131       //! Returns the storage of the i-th child (const version).
  132       /**
  133        * \returns a copy of the object storing the i-th child.
  134        */
  135       template<std::size_t i>
  136       std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
  137       {
  138         static_assert((i < CHILDREN), "child index out of range");
  139         return _children[i];
  140       }
  141 
  142       //! Sets the i-th child to the passed-in value.
  143       template<std::size_t i>
  144       void setChild (T& t, index_constant<i> = {})
  145       {
  146         static_assert((i < CHILDREN), "child index out of range");
  147         _children[i] = stackobject_to_shared_ptr(t);
  148       }
  149 
  150       //! Store the passed value in i-th child.
  151       template<std::size_t i>
  152       void setChild (T&& t, index_constant<i> = {})
  153       {
  154         static_assert((i < CHILDREN), "child index out of range");
  155         _children[i] = convert_arg(std::move(t));
  156       }
  157 
  158       //! Sets the stored value representing the i-th child to the passed-in value.
  159       template<std::size_t i>
  160       void setChild (std::shared_ptr<T> st, index_constant<i> = {})
  161       {
  162         static_assert((i < CHILDREN), "child index out of range");
  163         _children[i] = std::move(st);
  164       }
  165 
  166       //! @}
  167 
  168 
  169       //! @name Child Access (Dynamic methods)
  170       //! @{
  171 
  172       //! Returns the i-th child.
  173       /**
  174        * \returns a reference to the i-th child.
  175        */
  176       T& child (std::size_t i)
  177       {
  178         assert(i < CHILDREN && "child index out of range");
  179         return *_children[i];
  180       }
  181 
  182       //! Returns the i-th child (const version).
  183       /**
  184        * \returns a const reference to the i-th child.
  185        */
  186       const T& child (std::size_t i) const
  187       {
  188         assert(i < CHILDREN && "child index out of range");
  189         return *_children[i];
  190       }
  191 
  192       //! Returns the storage of the i-th child.
  193       /**
  194        * \returns a copy of the object storing the i-th child.
  195        */
  196       std::shared_ptr<T> childStorage (std::size_t i)
  197       {
  198         assert(i < CHILDREN && "child index out of range");
  199         return _children[i];
  200       }
  201 
  202       //! Returns the storage of the i-th child (const version).
  203       /**
  204        * \returns a copy of the object storing the i-th child.
  205        */
  206       std::shared_ptr<const T> childStorage (std::size_t i) const
  207       {
  208         assert(i < CHILDREN && "child index out of range");
  209         return _children[i];
  210       }
  211 
  212       //! Sets the i-th child to the passed-in value.
  213       void setChild (std::size_t i, T& t)
  214       {
  215         assert(i < CHILDREN && "child index out of range");
  216         _children[i] = stackobject_to_shared_ptr(t);
  217       }
  218 
  219       //! Store the passed value in i-th child.
  220       void setChild (std::size_t i, T&& t)
  221       {
  222         assert(i < CHILDREN && "child index out of range");
  223         _children[i] = convert_arg(std::move(t));
  224       }
  225 
  226       //! Sets the stored value representing the i-th child to the passed-in value.
  227       void setChild (std::size_t i, std::shared_ptr<T> st)
  228       {
  229         assert(i < CHILDREN && "child index out of range");
  230         _children[i] = std::move(st);
  231       }
  232 
  233       const NodeStorage& nodeStorage () const
  234       {
  235         return _children;
  236       }
  237 
  238       //! @}
  239 
  240       //! @name Nested Child Access
  241       //! @{
  242 
  243       // The following two methods require a little bit of SFINAE trickery to work correctly:
  244       // We have to make sure that they don't shadow the methods for direct child access because
  245       // those get called by the generic child() machinery. If that machinery picks up the methods
  246       // defined below, we have an infinite recursion.
  247       // So the methods make sure that either
  248       //
  249       // * there are more than one argument. In that case, we got multiple indices and can forward
  250       //   to the general machine.
  251       //
  252       // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
  253       //   The argument thus has to be some kind of TreePath instance that we can also pass to the
  254       //   generic machine.
  255       //
  256       // The above SFINAE logic works, but there is still a problem with the return type deduction.
  257       // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
  258       // type deduction will trigger the infinite recursion.
  259 
  260       //! Returns the child given by the list of indices.
  261       /**
  262        * This method simply forwards to the freestanding function child(). See that
  263        * function for further information.
  264        */
  265 #ifdef DOXYGEN
  266       template<typename... Indices>
  267       ImplementationDefined& child (Indices... indices)
  268 #else
  269       template<typename I0, typename... I,
  270         std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
  271       decltype(auto) child (I0 i0, I... i)
  272 #endif
  273       {
  274         static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
  275           "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
  276           );
  277         return Dune::TypeTree::child(*this,i0,i...);
  278       }
  279 
  280       //! Returns the child given by the list of indices.
  281       /**
  282        * This method simply forwards to the freestanding function child(). See that
  283        * function for further information.
  284        */
  285 #ifdef DOXYGEN
  286       template<typename... Indices>
  287       const ImplementationDefined& child (Indices... indices)
  288 #else
  289       template<typename I0, typename... I,
  290         std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
  291       decltype(auto) child (I0 i0, I... i) const
  292 #endif
  293       {
  294         static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
  295           "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
  296           );
  297         return Dune::TypeTree::child(*this,i0,i...);
  298       }
  299 
  300       //! @}
  301 
  302       //! @name Constructors
  303       //! @{
  304 
  305     protected:
  306 
  307       //! Default constructor.
  308       /**
  309        * The default constructor is protected, as PowerNode is a utility
  310        * class that needs to be filled with meaning by subclassing it
  311        * and adding useful functionality to the subclass.
  312        *
  313        * \warning When using the default constructor, make sure to set ALL children
  314        * by means of the setChild() methods!
  315        */
  316       PowerNode ()
  317       {}
  318 
  319       //! Initialize the PowerNode with a copy of the passed-in storage type.
  320       explicit PowerNode (const NodeStorage& children)
  321         : _children(children)
  322       {}
  323 
  324       //! Initialize all children with copies of a storage object constructed from the parameter \c t.
  325       explicit PowerNode (T& t, bool distinct_objects = true)
  326       {
  327         if (distinct_objects)
  328           {
  329             for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
  330               *it = std::make_shared<T>(t);
  331           }
  332         else
  333           {
  334             std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
  335             std::fill(_children.begin(),_children.end(),sp);
  336           }
  337       }
  338 
  339 #ifdef DOXYGEN
  340 
  341       //! Initialize all children with the passed-in objects.
  342       PowerNode(T& t1, T& t2, ...)
  343       {}
  344 
  345 #else
  346 
  347       template<typename... Children,
  348         std::enable_if_t<
  349           std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
  350           ,int> = 0>
  351       PowerNode (Children&&... children)
  352       {
  353         static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
  354         _children = NodeStorage{convert_arg(std::forward<Children>(children))...};
  355       }
  356 
  357       template<typename... Children,
  358         std::enable_if_t<
  359           std::conjunction<std::is_same<ChildType, Children>...>::value
  360           ,int> = 0>
  361       PowerNode (std::shared_ptr<Children>... children)
  362       {
  363         static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
  364         _children = NodeStorage{children...};
  365       }
  366 
  367 #endif // DOXYGEN
  368 
  369       //! @}
  370 
  371     private:
  372       NodeStorage _children;
  373     };
  374 
  375     //! \} group Nodes
  376 
  377   } // namespace TypeTree
  378 } //namespace Dune
  379 
  380 #endif // DUNE_TYPETREE_POWERNODE_HH