Loading...
Searching...
No Matches
powernode.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: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
#ifndef DUNE_TYPETREE_POWERNODE_HH
#define DUNE_TYPETREE_POWERNODE_HH
#include <cassert>
#include <array>
#include <memory>
#include <type_traits>
#include <dune/common/typetraits.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/typetree/nodetags.hh>
#include <dune/typetree/utility.hh>
#include <dune/typetree/childextraction.hh>
#include <dune/typetree/typetraits.hh>
namespace Dune {
namespace TypeTree {
#ifndef DOXYGEN
template<typename PowerNode, typename T, std::size_t k>
struct AssertPowerNodeChildCount
: public std::enable_if<std::is_same<
typename PowerNode::ChildType,
T>::value &&
PowerNode::degree() == k,
T>
{};
#endif
template<typename T, std::size_t k>
class PowerNode
{
public:
static const bool isLeaf = false;
static const bool isPower = true;
static const bool isComposite = false;
static constexpr auto degree ()
{
return std::integral_constant<std::size_t,k>{};
}
typedef PowerNodeTag NodeTag;
typedef T ChildType;
typedef std::array<std::shared_ptr<T>,k> NodeStorage;
template<std::size_t i>
struct Child
{
static_assert((i < degree()), "child index out of range");
typedef T Type;
typedef T type;
};
template<std::size_t i>
T& child (index_constant<i> = {})
{
static_assert((i < degree()), "child index out of range");
return *_children[i];
}
template<std::size_t i>
const T& child (index_constant<i> = {}) const
{
static_assert((i < degree()), "child index out of range");
return *_children[i];
}
template<std::size_t i>
std::shared_ptr<T> childStorage (index_constant<i> = {})
{
static_assert((i < degree()), "child index out of range");
return _children[i];
}
template<std::size_t i>
std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
{
static_assert((i < degree()), "child index out of range");
return _children[i];
}
template<std::size_t i>
void setChild (T& t, index_constant<i> = {})
{
static_assert((i < degree()), "child index out of range");
_children[i] = stackobject_to_shared_ptr(t);
}
template<std::size_t i>
void setChild (T&& t, index_constant<i> = {})
{
static_assert((i < degree()), "child index out of range");
_children[i] = convert_arg(std::move(t));
}
template<std::size_t i>
void setChild (std::shared_ptr<T> st, index_constant<i> = {})
{
static_assert((i < degree()), "child index out of range");
_children[i] = std::move(st);
}
T& child (std::size_t i)
{
assert(i < degree() && "child index out of range");
return *_children[i];
}
const T& child (std::size_t i) const
{
assert(i < degree() && "child index out of range");
return *_children[i];
}
std::shared_ptr<T> childStorage (std::size_t i)
{
assert(i < degree() && "child index out of range");
return _children[i];
}
std::shared_ptr<const T> childStorage (std::size_t i) const
{
assert(i < degree() && "child index out of range");
return _children[i];
}
void setChild (std::size_t i, T& t)
{
assert(i < degree() && "child index out of range");
_children[i] = stackobject_to_shared_ptr(t);
}
void setChild (std::size_t i, T&& t)
{
assert(i < degree() && "child index out of range");
_children[i] = convert_arg(std::move(t));
}
void setChild (std::size_t i, std::shared_ptr<T> st)
{
assert(i < degree() && "child index out of range");
_children[i] = std::move(st);
}
const NodeStorage& nodeStorage () const
{
return _children;
}
// The following two methods require a little bit of SFINAE trickery to work correctly:
// We have to make sure that they don't shadow the methods for direct child access because
// those get called by the generic child() machinery. If that machinery picks up the methods
// defined below, we have an infinite recursion.
// So the methods make sure that either
//
// * there are more than one argument. In that case, we got multiple indices and can forward
// to the general machine.
//
// * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
// The argument thus has to be some kind of TreePath instance that we can also pass to the
// generic machine.
//
// The above SFINAE logic works, but there is still a problem with the return type deduction.
// We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
// type deduction will trigger the infinite recursion.
#ifdef DOXYGEN
template<typename... Indices>
ImplementationDefined& child (Indices... indices)
#else
template<typename I0, typename... I,
std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
decltype(auto) child (I0 i0, I... i)
#endif
{
static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
"You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
);
return Dune::TypeTree::child(*this,i0,i...);
}
#ifdef DOXYGEN
template<typename... Indices>
const ImplementationDefined& child (Indices... indices)
#else
template<typename I0, typename... I,
std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
decltype(auto) child (I0 i0, I... i) const
#endif
{
static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
"You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
);
return Dune::TypeTree::child(*this,i0,i...);
}
protected:
PowerNode ()
{}
explicit PowerNode (const NodeStorage& children)
: _children(children)
{}
explicit PowerNode (T& t, bool distinct_objects = true)
{
if (distinct_objects)
{
for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
*it = std::make_shared<T>(t);
}
else
{
std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
std::fill(_children.begin(),_children.end(),sp);
}
}
#ifdef DOXYGEN
PowerNode(T& t1, T& t2, ...)
{}
#else
template<typename... Children,
std::enable_if_t<
std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
,int> = 0>
PowerNode (Children&&... children)
{
static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
_children = NodeStorage{convert_arg(std::forward<Children>(children))...};
}
template<typename... Children,
std::enable_if_t<
std::conjunction<std::is_same<ChildType, Children>...>::value
,int> = 0>
PowerNode (std::shared_ptr<Children>... children)
{
static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
_children = NodeStorage{children...};
}
#endif // DOXYGEN
private:
NodeStorage _children;
};
} // namespace TypeTree
} //namespace Dune
#endif // DUNE_TYPETREE_POWERNODE_HH
typetraits.hh
nodetags.hh
childextraction.hh
utility.hh
Dune
Definition accumulate_static.hh:17
Dune::TypeTree
Definition accumulate_static.hh:18
Dune::TypeTree::PowerNodeTag
Tag designating a power node.
Definition nodetags.hh:21
Dune::TypeTree::PowerNode::setChild
void setChild(T &t, index_constant< i >={})
Sets the i-th child to the passed-in value.
Definition powernode.hh:143
Dune::TypeTree::PowerNode::child
T & child(std::size_t i)
Returns the i-th child.
Definition powernode.hh:175
Dune::TypeTree::PowerNode::child
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition powernode.hh:113
Dune::TypeTree::PowerNode::setChild
void setChild(std::shared_ptr< T > st, index_constant< i >={})
Sets the stored value representing the i-th child to the passed-in value.
Definition powernode.hh:159
Dune::TypeTree::PowerNode::childStorage
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition powernode.hh:124
Dune::TypeTree::PowerNode::PowerNode
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition powernode.hh:341
Dune::TypeTree::PowerNode::nodeStorage
const NodeStorage & nodeStorage() const
Definition powernode.hh:232
Dune::TypeTree::PowerNode::NodeStorage
std::array< std::shared_ptr< T >, k > NodeStorage
The type used for storing the children.
Definition powernode.hh:77
Dune::TypeTree::PowerNode::childStorage
std::shared_ptr< const T > childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition powernode.hh:135
Dune::TypeTree::PowerNode::PowerNode
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition powernode.hh:324
Dune::TypeTree::PowerNode::NodeTag
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition powernode.hh:71
Dune::TypeTree::PowerNode::child
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition powernode.hh:185
Dune::TypeTree::PowerNode::degree
static constexpr auto degree()
Definition powernode.hh:65
Dune::TypeTree::PowerNode::childStorage
std::shared_ptr< const T > childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition powernode.hh:205
Dune::TypeTree::PowerNode::setChild
void setChild(std::size_t i, std::shared_ptr< T > st)
Sets the stored value representing the i-th child to the passed-in value.
Definition powernode.hh:226
Dune::TypeTree::PowerNode::isComposite
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition powernode.hh:63
Dune::TypeTree::PowerNode::isLeaf
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition powernode.hh:57
Dune::TypeTree::PowerNode::isPower
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition powernode.hh:60
Dune::TypeTree::PowerNode::PowerNode
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition powernode.hh:319
Dune::TypeTree::PowerNode::ChildType
T ChildType
The type of each child.
Definition powernode.hh:74
Dune::TypeTree::PowerNode::child
T & child(index_constant< i >={})
Returns the i-th child.
Definition powernode.hh:102
Dune::TypeTree::PowerNode::child
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition powernode.hh:266
Dune::TypeTree::PowerNode::setChild
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition powernode.hh:219
Dune::TypeTree::PowerNode::setChild
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition powernode.hh:151
Dune::TypeTree::PowerNode::PowerNode
PowerNode()
Default constructor.
Definition powernode.hh:315
Dune::TypeTree::PowerNode::child
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition powernode.hh:286
Dune::TypeTree::PowerNode::setChild
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition powernode.hh:212
Dune::TypeTree::PowerNode::childStorage
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition powernode.hh:195
Dune::TypeTree::PowerNode::Child
Access to the type and storage type of the i-th child.
Definition powernode.hh:83
Dune::TypeTree::PowerNode::Child::type
T type
The type of the child.
Definition powernode.hh:91
Dune::TypeTree::PowerNode::Child::Type
T Type
The type of the child.
Definition powernode.hh:88
Dune::TypeTree::IsTreePath
Check if type represents a tree path.
Definition typetraits.hh:184