"Fossies" - the Fresh Open Source Software Archive

Member "dune-typetree-2.8.0/dune/typetree/utility.hh" (31 Aug 2021, 10839 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 "utility.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: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    2 // vi: set et ts=4 sw=2 sts=2:
    3 
    4 #ifndef DUNE_TYPETREE_UTILITY_HH
    5 #define DUNE_TYPETREE_UTILITY_HH
    6 
    7 #include <memory>
    8 #include <tuple>
    9 #include <type_traits>
   10 #include <utility>
   11 #include <algorithm>
   12 
   13 #include <dune/common/shared_ptr.hh>
   14 #include <dune/common/indices.hh>
   15 #include <dune/common/hybridutilities.hh>
   16 #include <dune/typetree/nodeinterface.hh>
   17 #include <dune/typetree/nodetags.hh>
   18 
   19 namespace Dune {
   20   namespace TypeTree {
   21 
   22     /** \addtogroup TypeTree
   23      *  \{
   24      */
   25 
   26 #ifndef DOXYGEN
   27 
   28     template<typename T>
   29     std::shared_ptr<T> convert_arg(const T& t)
   30     {
   31       return std::make_shared<T>(t);
   32     }
   33 
   34     template<typename T>
   35     std::shared_ptr<T> convert_arg(T& t)
   36     {
   37       return stackobject_to_shared_ptr(t);
   38     }
   39 
   40     template<typename BaseType, typename T>
   41     T& assertGridViewType(T& t)
   42     {
   43       static_assert((std::is_same<typename BaseType::Traits::GridViewType,
   44                      typename T::Traits::GridViewType>::value),
   45                     "GridViewType must be equal in all components of composite type");
   46       return t;
   47     }
   48 
   49     // only bind to real rvalues
   50     template<typename T>
   51     typename std::enable_if<!std::is_lvalue_reference<T>::value,std::shared_ptr<T> >::type convert_arg(T&& t)
   52     {
   53       return std::make_shared<T>(std::forward<T>(t));
   54     }
   55 
   56 
   57     namespace Experimental {
   58 
   59       /**
   60        * @brief Applies left fold to a binary operator
   61        * @details End of recursion of the fold operator
   62        *
   63        * @param binary_op  Binary functor (discarded)
   64        * @param arg        Final result of the fold expansion
   65        * @return constexpr decltype(auto)  Final result of the fold expansion
   66        */
   67       template<class BinaryOp, class Arg>
   68       constexpr decltype(auto)
   69       left_fold(BinaryOp&& binary_op, Arg&& arg)
   70       {
   71         return std::forward<Arg>(arg);
   72       }
   73 
   74       /**
   75        * @brief Applies left fold to a binary operator
   76        * @details This function allows to pipe the result of one evaluation of a
   77        *          binary operator into the next evaluation.
   78        *
   79        * - C++17:   `(init op ... op pack);`
   80        * - here:    `left_fold(op, init, pack...);`
   81        *
   82        * @code {.c++}
   83        *   auto p = std::plus<>{};
   84        *   auto result_a = p(p(p(0,1),2),3);
   85        *   auto result_b = left_fold(std::move(p), 0, 1, 2, 3);
   86        * // result_a is same as result_b
   87        * @endcode
   88        *
   89        * @param binary_op  Binary functor
   90        * @param init       Initial (left-most) value of the fold
   91        * @param arg_0      First argument of the right side of the fold
   92        * @param args       Additional arguments of the right side of the fold
   93        * @return constexpr decltype(auto)  Final result of the fold expansion
   94        */
   95       template<class BinaryOp, class Init, class Arg0, class... Args>
   96       constexpr decltype(auto)
   97       left_fold(BinaryOp&& binary_op, Init&& init, Arg0&& arg_0, Args&&... args)
   98       {
   99         return left_fold(
  100           std::forward<BinaryOp>(binary_op),
  101           binary_op(std::forward<Init>(init), std::forward<Arg0>(arg_0)),
  102           std::forward<Args>(args)...);
  103       }
  104 
  105 
  106       namespace Hybrid {
  107         using namespace Dune::Hybrid;
  108 
  109         namespace Detail {
  110           template<class Op, class... Args>
  111           constexpr auto applyOperator(Op&& op, Args&&... args)
  112           {
  113             using T = std::common_type_t<Args...>;
  114             return op(static_cast<T>(args)...);
  115           }
  116 
  117           template<class Op, class T, T... Args>
  118           constexpr auto applyOperator(Op, std::integral_constant<T,Args>...)
  119           {
  120             static_assert(std::is_default_constructible_v<Op>,
  121               "Operator in integral expressions shall be default constructible");
  122             constexpr auto result = Op{}(T{Args}...);
  123             return std::integral_constant<std::decay_t<decltype(result)>,result>{};
  124           }
  125 
  126           // FIXME: use lambda when we adpot c++20
  127           struct Max {
  128             template<class... Args>
  129             constexpr auto operator()(Args&&... args) const
  130             {
  131               using T = std::common_type_t<Args...>;
  132               return std::max({static_cast<T>(args)...});
  133             }
  134           };
  135         }
  136 
  137         static constexpr auto max = [](const auto& a, const auto& b)
  138         {
  139           return Detail::applyOperator(Detail::Max{}, a, b);
  140         };
  141 
  142         static constexpr auto plus = [](const auto& a, const auto& b)
  143         {
  144           return Detail::applyOperator(std::plus<>{}, a, b);
  145         };
  146 
  147         static constexpr auto minus = [](const auto& a, const auto& b)
  148         {
  149           return Detail::applyOperator(std::minus<>{}, a, b);
  150         };
  151       } // namespace Hybrid
  152 
  153     } // namespace Experimental
  154 
  155 
  156 #endif // DOXYGEN
  157 
  158     //! Struct for obtaining some basic structural information about a TypeTree.
  159     /**
  160      * This struct extracts basic information about the passed TypeTree and
  161      * presents them in a static way suitable for use as compile-time constants.
  162      *
  163      * \tparam Tree  The TypeTree to examine.
  164      * \tparam Tag   Internal parameter, leave at default value.
  165      */
  166     template<typename Tree, typename Tag = StartTag>
  167     struct TreeInfo
  168     {
  169 
  170     private:
  171       // Start the tree traversal
  172       typedef TreeInfo<Tree,NodeTag<Tree>> NodeInfo;
  173 
  174     public:
  175 
  176       //! The depth of the TypeTree.
  177       static const std::size_t depth = NodeInfo::depth;
  178 
  179       //! The total number of nodes in the TypeTree.
  180       static const std::size_t nodeCount = NodeInfo::nodeCount;
  181 
  182       //! The number of leaf nodes in the TypeTree.
  183       static const std::size_t leafCount = NodeInfo::leafCount;
  184 
  185     };
  186 
  187 
  188 #ifndef DOXYGEN
  189 
  190     // ********************************************************************************
  191     // TreeInfo specializations for the different node types
  192     // ********************************************************************************
  193 
  194 
  195     // leaf node
  196     template<typename Node>
  197     struct TreeInfo<Node,LeafNodeTag>
  198     {
  199 
  200       static const std::size_t depth = 1;
  201 
  202       static const std::size_t nodeCount = 1;
  203 
  204       static const std::size_t leafCount = 1;
  205 
  206     };
  207 
  208 
  209     // power node - exploit the fact that all children are identical
  210     template<typename Node>
  211     struct TreeInfo<Node,PowerNodeTag>
  212     {
  213 
  214       typedef TreeInfo<typename Node::ChildType,NodeTag<typename Node::ChildType>> ChildInfo;
  215 
  216       static const std::size_t depth = 1 + ChildInfo::depth;
  217 
  218       static const std::size_t nodeCount = 1 + StaticDegree<Node>::value * ChildInfo::nodeCount;
  219 
  220       static const std::size_t leafCount = StaticDegree<Node>::value * ChildInfo::leafCount;
  221 
  222     };
  223 
  224 
  225     namespace {
  226 
  227       // TMP for iterating over the children of a composite node
  228       // identical for both composite node implementations
  229       template<typename Node, std::size_t k, std::size_t n>
  230       struct generic_compositenode_children_info
  231       {
  232 
  233         typedef generic_compositenode_children_info<Node,k+1,n> NextChild;
  234 
  235         // extract child info
  236         typedef typename Node::template Child<k>::Type Child;
  237         typedef NodeTag<Child> ChildTag;
  238         typedef TreeInfo<Child,ChildTag> ChildInfo;
  239 
  240         // combine information of current child with info about following children
  241         static const std::size_t maxDepth = ChildInfo::depth > NextChild::maxDepth ? ChildInfo::depth : NextChild::maxDepth;
  242 
  243         static const std::size_t nodeCount = ChildInfo::nodeCount + NextChild::nodeCount;
  244 
  245         static const std::size_t leafCount = ChildInfo::leafCount + NextChild::leafCount;
  246 
  247       };
  248 
  249       // End of recursion
  250       template<typename Node, std::size_t n>
  251       struct generic_compositenode_children_info<Node,n,n>
  252       {
  253         static const std::size_t maxDepth = 0;
  254 
  255         static const std::size_t nodeCount = 0;
  256 
  257         static const std::size_t leafCount = 0;
  258       };
  259 
  260     } // anonymous namespace
  261 
  262 
  263       // Struct for building information about composite node
  264     template<typename Node>
  265     struct GenericCompositeNodeInfo
  266     {
  267 
  268       typedef generic_compositenode_children_info<Node,0,StaticDegree<Node>::value> Children;
  269 
  270       static const std::size_t depth = 1 + Children::maxDepth;
  271 
  272       static const std::size_t nodeCount = 1 + Children::nodeCount;
  273 
  274       static const std::size_t leafCount = Children::leafCount;
  275 
  276     };
  277 
  278 
  279     // CompositeNode: delegate to GenericCompositeNodeInfo
  280     template<typename Node>
  281     struct TreeInfo<Node,CompositeNodeTag>
  282       : public GenericCompositeNodeInfo<Node>
  283     {};
  284 
  285 
  286 #endif // DOXYGEN
  287 
  288 
  289     using Dune::index_constant;
  290     namespace Indices = Dune::Indices;
  291 
  292     //! No-op function to make calling a function on a variadic template argument pack legal C++.
  293     template<typename... Args>
  294     void discard(Args&&... args)
  295     {}
  296 
  297     //! Policies for the function apply_to_tuple().
  298     namespace apply_to_tuple_policy {
  299 
  300       //! Do not pass the index of the current tuple to the functor
  301       struct no_pass_index {};
  302 
  303       //! Pass the index of the current tuple to the functor as its first argument in a std::integral_constant.
  304       struct pass_index {};
  305 
  306       //! Default policy.
  307       typedef no_pass_index default_policy;
  308 
  309     }
  310 
  311     namespace {
  312 
  313       // version that does not pass index
  314       template<typename T, typename F, std::size_t... i>
  315       void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::no_pass_index)
  316       {
  317         discard((f(std::get<i>(std::forward<T>(t))),0)...);
  318       }
  319 
  320       // version that passes index
  321       template<typename T, typename F, std::size_t... i>
  322       void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::pass_index)
  323       {
  324         discard((f(index_constant<i>{},std::get<i>(std::forward<T>(t))),0)...);
  325       }
  326 
  327     }
  328 
  329     //! Apply a functor to each element of a std::tuple.
  330     /*
  331      * This function applies the functor f to each element of the std::tuple t.
  332      * It works for arbitrary combinations of const- and non const lvalues and rvalues.
  333      * The function accepts an optional policy argument that can currently be used to make
  334      * it pass the index of the current tuple argument to the functor as a compile time constant
  335      * in addition to the tuple element itself.
  336      */
  337     template<typename T, typename F, typename Policy>
  338     void apply_to_tuple(T&& t, F&& f, Policy = apply_to_tuple_policy::default_policy())
  339     {
  340       const std::size_t size = std::tuple_size<typename std::decay<T>::type>::value;
  341       _apply_to_tuple(
  342         std::forward<T>(t),
  343         std::forward<F>(f),
  344         std::make_index_sequence<size>{},
  345         Policy()
  346         );
  347     }
  348 
  349     //! \} group TypeTree
  350 
  351   } // namespace TypeTree
  352 } //namespace Dune
  353 
  354 #endif // DUNE_TYPETREE_UTILITY_HH