Commit 5e742118 authored by Simon Praetorius's avatar Simon Praetorius

cleaned up child extraction

parent cc191ed6
Pipeline #26138 failed with stage
in 1 minute and 22 seconds
......@@ -4,9 +4,10 @@ Changes
TypeTree 2.8-git
----------------
- Removed the free function `childStorage()`
- Removed the type aliases for the storage type `Storage` and `ConstStorage` in the
node implementations.
- The memberfunction `childStorage()` in the nodes now consistently take an index or an
index_constant as argument.
TypeTree 2.7
......
......@@ -4,6 +4,7 @@
#ifndef DUNE_TYPETREE_CHILDEXTRACTION_HH
#define DUNE_TYPETREE_CHILDEXTRACTION_HH
#include <type_traits>
#include <utility>
#include <dune/common/concept.hh>
......@@ -25,85 +26,75 @@ namespace Dune {
#ifndef DOXYGEN
namespace impl {
namespace Impl {
// ********************************************************************************
// end of the recursion, there are no child indices, so just return the node itself
// ********************************************************************************
// check at run time whether index is a valid child index
template <class Node, class Index>
std::true_type checkChildIndex(Node const& node, Index i)
{
assert(i < node.degree() && "Child index out of range");
return {};
}
template<typename Node>
auto child(Node&& node) -> decltype(std::forward<Node>(node))
// check at compile time whether index is a valid index
template <class Node, std::size_t i>
std::bool_constant<(i < Node::degree())> checkChildIndex(Node const& node, index_constant<i>)
{
return std::forward<Node>(node);
static_assert(i < node.degree(), "Child index out of range");
return {};
}
// ********************************************************************************
// next index is a compile-time constant
// ********************************************************************************
// finally return the node itself if no further indices are provided. Break condition
// for the recursion over the node childs.
template<class Node>
decltype(auto) childImpl (Node&& node)
{
return std::forward<Node>(node);
}
// we need a concept to make sure that the node has a templated child()
// method
struct HasTemplateChildMethod {
template <class Node>
auto require(const Node& node) -> decltype(node.template child<0>());
};
template<class Node>
auto childStorageImpl (Node&& node)
{
return std::forward<Node>(node);
}
// The actual implementation is rather simple, we just use an overload that requires the first index
// to be an index_constant, get the child and then recurse.
// It only gets ugly due to the enable_if, but without that trick, the error messages for the user
// can get *very* obscure (they are bad enough as it is).
template<typename Node, std::size_t i, typename... J,
typename std::enable_if<
Dune::models<HasTemplateChildMethod, Node>() &&
(i < StaticDegree<Node>::value), int>::type = 0>
decltype(auto) child(Node&& node, index_constant<i>, J... j)
// recursively call `node.child(...)` with the given indices
template<class Node, class I0, class... I>
decltype(auto) childImpl (Node&& node, I0 i0, I... i)
{
return child(std::forward<Node>(node).template child<i>(),j...);
auto valid = checkChildIndex(node,i0);
if constexpr (valid)
return childImpl(node.child(i0),i...);
else
return;
}
// This overload is only present to give useful compiler
// error messages via static_assert in case the other overloads
// fail.
template<typename Node, std::size_t i, typename... J,
typename std::enable_if<
(!Dune::models<HasTemplateChildMethod, Node>()) ||
(i >= StaticDegree<Node>::value), int>::type = 0>
void child(Node&& node, index_constant<i>, J... j)
// recursively call `node.childStorage(...)` with the given indices
template<class Node, class I0, class... I>
decltype(auto) childStorageImpl (Node&& node, I0 i0, I... i)
{
static_assert(Dune::models<HasTemplateChildMethod, Node>(), "Node does not have a template method child()");
static_assert(i < StaticDegree<Node>::value, "Child index out of range");
auto valid = checkChildIndex(node,i0);
if constexpr (valid)
return childStorageImpl(node->childStorage(i0),i...);
else
return;
}
// ********************************************************************************
// next index is a run-time value
// ********************************************************************************
// The actual implemention here overloads on std::size_t. It is a little less ugly because it currently
// has a hard requirement on the PowerNode Tag (although only using is_convertible, as tags can be
// inherited (important!).
template<typename Node, typename... J>
decltype(auto)
child(
Node&& node,
std::enable_if_t<
std::is_convertible<
NodeTag<Node>,
PowerNodeTag
>{},
std::size_t> i,
J... j
)
// forward to the impl methods by extracting the indices from the treepath
template<class Node, class... Indices, std::size_t... i>
decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
{
return child(std::forward<Node>(node).child(i),j...);
return childImpl(std::forward<Node>(node),treePathEntry<i>(tp)...);
}
template<typename Node, typename... Indices, std::size_t... i>
decltype(auto) child(Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
// forward to the impl methods by extracting the indices from the treepath
template<class Node, class... Indices, std::size_t... i>
decltype(auto) childStorage (Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
{
return child(std::forward<Node>(node),treePathEntry<i>(tp)...);
return childStorageImpl(std::forward<Node>(node),treePathEntry<i>(tp)...);
}
} // namespace imp
} // end namespace Impl
#endif // DOXYGEN
......@@ -134,10 +125,21 @@ namespace Dune {
#ifdef DOXYGEN
ImplementationDefined child(Node&& node, Indices... indices)
#else
decltype(auto) child(Node&& node, Indices... indices)
decltype(auto) child (Node&& node, Indices... indices)
#endif
{
return impl::child(std::forward<Node>(node),indices...);
return Impl::childImpl(std::forward<Node>(node),indices...);
}
template<typename Node, typename... Indices>
#ifdef DOXYGEN
ImplementationDefined childStorage(Node&& node, Indices... indices)
#else
auto childStorage (Node&& node, Indices... indices)
#endif
{
static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices");
return Impl::childStorageImpl(&node,indices...);
}
//! Extracts the child of a node given by a static TreePath object.
......@@ -163,10 +165,21 @@ namespace Dune {
#ifdef DOXYGEN
ImplementationDefined child(Node&& node, TreePath<Indices...> treePath)
#else
decltype(auto) child(Node&& node, TreePath<Indices...>)
decltype(auto) child (Node&& node, TreePath<Indices...>)
#endif
{
return Impl::childImpl(std::forward<Node>(node),index_constant<Indices>{}...);
}
template<typename Node, std::size_t... Indices>
#ifdef DOXYGEN
ImplementationDefined childStorage(Node&& node, TreePath<Indices...> treePath)
#else
auto childStorage (Node&& node, TreePath<Indices...>)
#endif
{
return child(std::forward<Node>(node),index_constant<Indices>{}...);
static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
return Impl::childStorageImpl(&node,index_constant<Indices>{}...);
}
//! Extracts the child of a node given by a HybridTreePath object.
......@@ -197,10 +210,21 @@ namespace Dune {
#ifdef DOXYGEN
ImplementationDefined child(Node&& node, HybridTreePath<Indices...> treePath)
#else
decltype(auto) child(Node&& node, HybridTreePath<Indices...> tp)
decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp)
#endif
{
return Impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
}
template<typename Node, typename... Indices>
#ifdef DOXYGEN
ImplementationDefined child(Node&& node, HybridTreePath<Indices...> treePath)
#else
auto childStorage (Node&& node, HybridTreePath<Indices...> tp)
#endif
{
return impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
return Impl::childStorage(&node,tp,std::index_sequence_for<Indices...>{});
}
......
......@@ -47,7 +47,7 @@ namespace Dune {
//! The number of children.
static const std::size_t CHILDREN = sizeof...(Children);
static constexpr std::size_t degree()
static constexpr std::size_t degree ()
{
return sizeof...(Children);
}
......@@ -73,7 +73,7 @@ namespace Dune {
* \returns a reference to the k-th child.
*/
template<std::size_t k>
auto& child (index_constant<k> = {})
typename Child<k>::Type& child (index_constant<k> = {})
{
return *std::get<k>(_children);
}
......@@ -83,7 +83,7 @@ namespace Dune {
* \returns a const reference to the k-th child.
*/
template<std::size_t k>
const auto& child (index_constant<k> = {}) const
const typename Child<k>::Type& child (index_constant<k> = {}) const
{
return *std::get<k>(_children);
}
......@@ -93,7 +93,7 @@ namespace Dune {
* \returns a copy of the object storing the k-th child.
*/
template<std::size_t k>
auto childStorage (index_constant<k> = {})
std::shared_ptr<typename Child<k>::Type> childStorage (index_constant<k> = {})
{
return std::get<k>(_children);
}
......@@ -103,7 +103,7 @@ namespace Dune {
* \returns a copy of the object storing the k-th child.
*/
template<std::size_t k>
auto childStorage (index_constant<k> = {}) const
std::shared_ptr<const typename Child<k>::Type> childStorage (index_constant<k> = {}) const
{
return std::get<k>(_children);
}
......
......@@ -122,7 +122,7 @@ namespace Dune {
* \returns a copy of the object storing the i-th child.
*/
template<std::size_t i>
auto childStorage (index_constant<i> = {})
std::shared_ptr<T> childStorage (index_constant<i> = {})
{
static_assert((i < CHILDREN), "child index out of range");
return _children[i];
......@@ -133,7 +133,7 @@ namespace Dune {
* \returns a copy of the object storing the i-th child.
*/
template<std::size_t i>
auto childStorage (index_constant<i> = {}) const
std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
{
static_assert((i < CHILDREN), "child index out of range");
return _children[i];
......@@ -193,7 +193,7 @@ namespace Dune {
/**
* \returns a copy of the object storing the i-th child.
*/
auto childStorage (std::size_t i)
std::shared_ptr<T> childStorage (std::size_t i)
{
assert(i < CHILDREN && "child index out of range");
return _children[i];
......@@ -203,7 +203,7 @@ namespace Dune {
/**
* \returns a copy of the object storing the i-th child.
*/
auto childStorage (std::size_t i) const
std::shared_ptr<const T> childStorage (std::size_t i) const
{
assert(i < CHILDREN && "child index out of range");
return _children[i];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment