Loading...
Searching...
No Matches
treecontainer.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
#ifndef DUNE_COMMON_TYPETREE_TREECONTAINER_HH
#define DUNE_COMMON_TYPETREE_TREECONTAINER_HH
#include <type_traits>
#include <utility>
#include <functional>
#include <array>
#include <dune/common/indices.hh>
#include <dune/common/hybridutilities.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/common/tuplevector.hh>
#include <dune/common/typetree/nodeconcepts.hh>
#include <dune/common/typetree/treepath.hh>
namespace Dune::TypeTree {
namespace Impl {
template<class LeafToValue>
class ContainerFactory
{
public:
ContainerFactory(LeafToValue leafToValue) :
leafToValue_(leafToValue)
{}
template<class Node>
requires Dune::TypeTree::Concept::TreeNode<Node>
auto operator()(const Node& node)
{
if constexpr (Dune::TypeTree::Concept::LeafTreeNode<Node>)
return leafToValue_(node);
else
{
if constexpr (Dune::TypeTree::Concept::UniformInnerTreeNode<Node>)
{
if constexpr (Dune::TypeTree::Concept::StaticDegreeInnerTreeNode<Node>)
{
return Dune::unpackIntegerSequence([&](auto... indices) {
return std::array{(*this)(node.child(indices))...};
}, std::make_index_sequence<std::size_t(Node::degree())>());
}
else
{
using TransformedChild = decltype((*this)(node.child(0)));
std::vector<TransformedChild> container;
container.reserve(node.degree());
for (std::size_t i = 0; i < node.degree(); ++i)
container.emplace_back((*this)(node.child(i)));
return container;
}
}
else
{
return Dune::unpackIntegerSequence([&](auto... indices) {
return Dune::makeTupleVector((*this)(node.child(indices))...);
}, std::make_index_sequence<std::size_t(Node::degree())>());
}
}
}
private:
LeafToValue leafToValue_;
};
/*
* \brief Wrap nested container to provide a VectorBackend
*/
template<class Container>
class TreeContainerVectorBackend
{
template<class C>
static constexpr decltype(auto) accessByTreePath(C&& container, const TreePath<>& path)
{
return container;
}
template<class C, class... T>
static constexpr decltype(auto) accessByTreePath(C&& container, const TreePath<T...>& path)
{
auto head = path[Dune::Indices::_0];
auto tailPath = Dune::unpackIntegerSequence([&](auto... i){
return treePath(path[Dune::index_constant<i+1>{}]...);
}, std::make_index_sequence<sizeof...(T)-1>());
return accessByTreePath(container[head], tailPath);
}
template<class C, class Tree>
static void recursiveResize(C& container, const Tree& tree)
{
if constexpr (not Dune::TypeTree::Concept::LeafTreeNode<Tree>)
{
if constexpr (requires { container.resize(0u); })
container.resize(tree.degree());
Dune::Hybrid::forEach(Dune::range(tree.degree()), [&](auto i) {
recursiveResize(container[i], tree.child(i));
});
}
}
public:
TreeContainerVectorBackend(Container&& container) :
container_(std::move(container))
{}
template <class Tree>
requires Dune::TypeTree::Concept::TreeNode<Tree>
TreeContainerVectorBackend(const Tree& tree) :
TreeContainerVectorBackend()
{
this->resize(tree);
}
template <class C = Container,
std::enable_if_t<std::is_default_constructible_v<C>, bool> = true>
TreeContainerVectorBackend() :
container_()
{}
template<class... T>
decltype(auto) operator[](const TreePath<T...>& path) const
{
return accessByTreePath(container_, path);
}
template<class... T>
decltype(auto) operator[](const TreePath<T...>& path)
{
return accessByTreePath(container_, path);
}
template<class Tree>
requires Dune::TypeTree::Concept::TreeNode<Tree>
void resize(const Tree& tree)
{
recursiveResize(container_, tree);
}
const Container& data() const
{
return container_;
}
Container& data()
{
return container_;
}
private:
Container container_;
};
template<class Container>
auto makeTreeContainerVectorBackend(Container&& container)
{
return TreeContainerVectorBackend<std::decay_t<Container>>(std::forward<Container>(container));
}
/*
* \brief A simple lambda for creating default constructible values from a node
*
* This simply returns LeafToValue<Node>{} for a given Node. It's needed
* because using a lambda expression in a using declaration is not allowed
* because it's an unevaluated context.
*/
template<template<class Node> class LeafToValue>
struct LeafToDefaultConstructibleValue
{
template<class Node>
auto operator()(const Node& node) const
{
return LeafToValue<Node>{};
}
};
} // namespace Impl
template<class Tree, class LeafToValue>
auto makeTreeContainer(const Tree& tree, LeafToValue&& leafToValue)
{
auto f = std::ref(leafToValue);
auto factory = Impl::ContainerFactory<decltype(f)>(f);
return Impl::makeTreeContainerVectorBackend(factory(tree));
}
template<class Value, class Tree>
auto makeTreeContainer(const Tree& tree)
{
return makeTreeContainer(tree, [](const auto&) {return Value{};});
}
template<class Value, class Tree>
using UniformTreeContainer = std::decay_t<decltype(makeTreeContainer<Value>(std::declval<const Tree&>()))>;
template<template<class Node> class LeafToValue, class Tree>
using TreeContainer = std::decay_t<decltype(makeTreeContainer(std::declval<const Tree&>(), std::declval<Impl::LeafToDefaultConstructibleValue<LeafToValue>>()))>;
} //namespace Dune::TypeTree
#endif // DUNE_COMMON_TYPETREE_TREECONTAINER_HH
tuplevector.hh
Provides the TupleVector class that augments std::tuple by operator[].
indices.hh
hybridutilities.hh
treepath.hh
nodeconcepts.hh
rangeutilities.hh
Utilities for reduction like operations on ranges.
Dune::Indices::_0
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition indices.hh:52
Dune::unpackIntegerSequence
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition indices.hh:124
Dune::index_constant
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition indices.hh:29
Dune::range
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
free standing function for setting up a range based for loop over an integer range for (auto i: range...
Definition rangeutilities.hh:288
Dune::Hybrid::forEach
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition hybridutilities.hh:261
Dune::TypeTree::makeTreeContainer
auto makeTreeContainer(const Tree &tree, LeafToValue &&leafToValue)
Create container having the same structure as the given tree.
Definition treecontainer.hh:230
Dune::TypeTree::UniformTreeContainer
std::decay_t< decltype(makeTreeContainer< Value >(std::declval< const Tree & >()))> UniformTreeContainer
Alias to container type generated by makeTreeContainer for given tree type and uniform value type.
Definition treecontainer.hh:262
Dune::TypeTree::TreeContainer
std::decay_t< decltype(makeTreeContainer(std::declval< const Tree & >(), std::declval< Impl::LeafToDefaultConstructibleValue< LeafToValue > >()))> TreeContainer
Alias to container type generated by makeTreeContainer for give tree type and when using LeafToValue ...
Definition treecontainer.hh:268
Dune::TypeTree::TreePath
Dune::HybridMultiIndex< T... > TreePath
A type for representing tree paths that supports both compile time and run time indices.
Definition treepath.hh:43
Dune::TypeTree::treePath
constexpr auto treePath(const T &... t)
Constructs a new TreePath from the given indices.
Definition treepath.hh:55
Dune::head
constexpr std::integral_constant< T, I0 > head(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the single head element.
Definition integersequence.hh:53
Dune::makeTupleVector
constexpr auto makeTupleVector(T &&... t)
Definition tuplevector.hh:108
Dune::TypeTree
Definition childaccess.hh:23