Skip to content
Snippets Groups Projects
Commit 83170d02 authored by Marco Agnese's avatar Marco Agnese Committed by Christoph Grüninger
Browse files

Use Hybrid::forEach instead of reimplementing the recursions and re-enable utilitytest

parent f58efb31
No related branches found
No related tags found
No related merge requests found
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include <array> #include <array>
#include "dune/common/streamoperators.hh" #include <dune/common/streamoperators.hh>
#include "dune/common/std/make_array.hh" #include <dune/common/std/make_array.hh>
namespace Dune namespace Dune
{ {
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include <utility> #include <utility>
#include <dune/common/hybridutilities.hh>
#include <dune/common/std/utility.hh>
/** \file /** \file
* \brief A static for loop for template meta-programming * \brief A static for loop for template meta-programming
*/ */
...@@ -13,46 +16,6 @@ ...@@ -13,46 +16,6 @@
namespace Dune namespace Dune
{ {
#ifndef DOXYGEN
// GenericForLoop
// --------------
template< template< class, class > class Operation, template< int > class Value, int first, int last >
class GenericForLoop
: public Operation< Value< first >, GenericForLoop< Operation, Value, first+1, last > >
{
static_assert( (first <= last), "GenericForLoop: first > last" );
};
template< template< class, class > class Operation, template< int > class Value, int last >
class GenericForLoop< Operation, Value, last, last >
: public Value< last >
{};
// ForLoopHelper
// -------------
namespace ForLoopHelper
{
template< class A, class B >
struct Apply
{
template< typename... Params >
static void apply ( Params&&... params )
{
A::apply( std::forward<Params>(params)... );
B::apply( std::forward<Params>(params)... );
}
};
} // end namespace ForLoopHelper
#endif
/** \class ForLoop /** \class ForLoop
* @brief A static loop using TMP * @brief A static loop using TMP
* *
...@@ -62,8 +25,8 @@ namespace Dune ...@@ -62,8 +25,8 @@ namespace Dune
* which is called for i=first...last (first<=last are int template arguments). * which is called for i=first...last (first<=last are int template arguments).
* A specialization for class template class Operation for i=first * A specialization for class template class Operation for i=first
* or i=last is not required. The class Operation must provide a * or i=last is not required. The class Operation must provide a
* static void function apply(...). Arguments (as references) * static void function apply(...). Arguments are perfectly forwarded
* can be passed through the ForLoop to this function. * through the ForLoop to this function.
* *
* It is possible to pass a subclass to the ForLoop * It is possible to pass a subclass to the ForLoop
* (since no specialization is needed). * (since no specialization is needed).
...@@ -98,17 +61,18 @@ namespace Dune ...@@ -98,17 +61,18 @@ namespace Dune
* } * }
* }; * };
* \endcode * \endcode
*
* \note Since Dune 2.4, ForLoop uses variadic templates and perfect forwarding and
* thus supports arbitrary numbers of arguments to apply(), which can be any
* combination of lvalues and rvalues.
*
*/ */
template< template< int > class Operation, int first, int last > template< template< int > class Operation, int first, int last >
class ForLoop struct ForLoop
: public GenericForLoop< ForLoopHelper::Apply, Operation, first, last >
{ {
static_assert( (first <= last), "ForLoop: first > last" ); static_assert( (first <= last), "ForLoop: first > last" );
template<typename... Args>
static void apply(Args&&... args)
{
Hybrid::forEach(Std::make_index_sequence<last+1-first>{},
[&](auto i){Operation<i+first>::apply(std::forward<Args>(args)...);});
}
}; };
} }
......
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
*/ */
#include <array> #include <array>
#include <ostream>
#include <tuple> #include <tuple>
#include <dune/common/forloop.hh> #include <dune/common/hybridutilities.hh>
#include <dune/common/std/utility.hh>
namespace Dune namespace Dune
{ {
...@@ -21,29 +21,6 @@ namespace Dune ...@@ -21,29 +21,6 @@ namespace Dune
@{ @{
*/ */
namespace
{
template<int i>
struct PrintTupleElement
{
template<typename Stream, typename Tuple>
static void apply(Stream& stream, const Tuple& t)
{
stream<<std::get<i>(t)<<",";
}
};
template<int i>
struct ReadTupleElement
{
template<typename Stream, typename Tuple>
static void apply(Stream& stream, Tuple& t)
{
stream>>std::get<i>(t);
}
};
}
//! Print a std::tuple //! Print a std::tuple
template<typename Stream, typename... Ts> template<typename Stream, typename... Ts>
inline Stream& operator<<(Stream& stream, const std::tuple<Ts...>& t) inline Stream& operator<<(Stream& stream, const std::tuple<Ts...>& t)
...@@ -51,7 +28,8 @@ namespace Dune ...@@ -51,7 +28,8 @@ namespace Dune
stream<<"["; stream<<"[";
if(sizeof...(Ts)>0) if(sizeof...(Ts)>0)
{ {
ForLoop<PrintTupleElement, 0, sizeof...(Ts)-2>::apply(stream, t); Hybrid::forEach(Std::make_index_sequence<sizeof...(Ts)-1>{},
[&](auto i){stream<<std::get<i>(t)<<",";});
stream<<std::get<sizeof...(Ts)-1>(t); stream<<std::get<sizeof...(Ts)-1>(t);
} }
stream<<"]"; stream<<"]";
...@@ -62,7 +40,8 @@ namespace Dune ...@@ -62,7 +40,8 @@ namespace Dune
template<typename Stream, typename... Ts> template<typename Stream, typename... Ts>
inline Stream& operator>>(Stream& stream, std::tuple<Ts...>& t) inline Stream& operator>>(Stream& stream, std::tuple<Ts...>& t)
{ {
ForLoop<ReadTupleElement, 0, sizeof...(Ts)-1>::apply(stream, t); Hybrid::forEach(Std::make_index_sequence<sizeof...(Ts)>{},
[&](auto i){stream>>std::get<i>(t);});
return stream; return stream;
} }
......
...@@ -202,7 +202,7 @@ dune_add_test(SOURCES testfloatcmp.cc) ...@@ -202,7 +202,7 @@ dune_add_test(SOURCES testfloatcmp.cc)
dune_add_test(SOURCES tupleutilitytest.cc) dune_add_test(SOURCES tupleutilitytest.cc)
#dune_add_test(SOURCES utilitytest.cc) dune_add_test(SOURCES utilitytest.cc)
dune_add_test(SOURCES eigenvaluestest.cc dune_add_test(SOURCES eigenvaluestest.cc
LINK_LIBRARIES dunecommon LINK_LIBRARIES dunecommon
......
...@@ -30,27 +30,26 @@ struct Counter { ...@@ -30,27 +30,26 @@ struct Counter {
int main(int, char**) int main(int, char**)
{ {
typedef std::tuple<int*,double*,long*,char*> PointerTuple; typedef std::tuple<int*,double*,long*,char*> PointerTuple;
PointerTuple pointers = Dune::NullPointerInitialiser<PointerTuple>::apply();
std::tuple<int*,double*,long*,char*> pointers = Dune::NullPointerInitialiser<PointerTuple>::apply();
int ret=0; int ret=0;
if(std::get<0>(pointers)!=0) { if(std::get<0>(pointers)!=nullptr) {
std::cerr<<"First pointer not null"<<std::endl; std::cerr<<"First pointer not null"<<std::endl;
ret=1; ret=1;
} }
if(std::get<1>(pointers)!=0) { if(std::get<1>(pointers)!=nullptr) {
std::cerr<<"Second pointer not null"<<std::endl; std::cerr<<"Second pointer not null"<<std::endl;
ret=2; ret=2;
} }
if(std::get<2>(pointers)!=0) { if(std::get<2>(pointers)!=nullptr) {
std::cerr<<"Third pointer not null"<<std::endl; std::cerr<<"Third pointer not null"<<std::endl;
ret=3; ret=3;
} }
if(std::get<3>(pointers)!=0) { if(std::get<3>(pointers)!=nullptr) {
std::cerr<<"Fourth pointer not null"<<std::endl; std::cerr<<"Fourth pointer not null"<<std::endl;
ret=4; ret=4;
} }
...@@ -70,15 +69,19 @@ int main(int, char**) ...@@ -70,15 +69,19 @@ int main(int, char**)
Tuple1 t1(i,c,l,c); Tuple1 t1(i,c,l,c);
RefTuple1 refs(i, c, l, c); RefTuple1 refs(i, c, l, c);
#if 0
DUNE_UNUSED RefTuple1 refs2(Dune::transformTuple<Dune::AddRefTypeEvaluator>(t1)); DUNE_UNUSED RefTuple1 refs2(Dune::transformTuple<Dune::AddRefTypeEvaluator>(t1));
PointerTuple1 pointers1 PointerTuple1 pointers1(Dune::transformTuple<Dune::AddPtrTypeEvaluator>(refs));
(Dune::transformTuple<Dune::AddPtrTypeEvaluator>(refs));
if(&i != std::get<0>(pointers1) || &c != std::get<1>(pointers1) || if(&i != std::get<0>(pointers1) || &c != std::get<1>(pointers1) ||
&l != std::get<2>(pointers1) || &c != std::get<3>(pointers1)) { &l != std::get<2>(pointers1) || &c != std::get<3>(pointers1)) {
std::cerr << "utilitytest: error: incorrect pointers in pointers1" std::cerr << "utilitytest: error: incorrect pointers in pointers1"
<< std::endl; << std::endl;
ret = 1; ret = 1;
} }
#endif
PointerTuple1 pointers1 = Dune::NullPointerInitialiser<PointerTuple1>::apply();
if(static_cast<size_t>(std::tuple_size<PointerTuple>::value) != static_cast<size_t>(std::tuple_size<PointerTuple>::value)) { if(static_cast<size_t>(std::tuple_size<PointerTuple>::value) != static_cast<size_t>(std::tuple_size<PointerTuple>::value)) {
std::cerr<<"Length and size do not match!"<<std::endl; std::cerr<<"Length and size do not match!"<<std::endl;
...@@ -90,8 +93,6 @@ int main(int, char**) ...@@ -90,8 +93,6 @@ int main(int, char**)
forEach.apply(count); forEach.apply(count);
std::cout << "Number of elements is: " << count.result_ << std::endl; std::cout << "Number of elements is: " << count.result_ << std::endl;
Dune::ForEachValuePair<PointerTuple,PointerTuple1> foreach1(pointers, pointers1); Dune::ForEachValuePair<PointerTuple,PointerTuple1> foreach1(pointers, pointers1);
foreach1.apply(count); foreach1.apply(count);
...@@ -105,6 +106,10 @@ int main(int, char**) ...@@ -105,6 +106,10 @@ int main(int, char**)
typedef Dune::ForEachType<Eval,PointerTuple1>::Type ConvertedType DUNE_UNUSED; typedef Dune::ForEachType<Eval,PointerTuple1>::Type ConvertedType DUNE_UNUSED;
Dune::PointerPairDeletor<PointerTuple1>::apply(p); Dune::PointerPairDeletor<PointerTuple1>::apply(p);
if(p != PointerTuple1(nullptr,nullptr,nullptr,nullptr)){
ret+=20;
std::cerr<<"PointerPairDeletor not working!"<<std::endl;
}
return ret; return ret;
} }
...@@ -5,12 +5,10 @@ ...@@ -5,12 +5,10 @@
#define DUNE_TUPLE_UTILITY_HH #define DUNE_TUPLE_UTILITY_HH
#include <cstddef> #include <cstddef>
#include <iostream>
#include <tuple> #include <tuple>
#include <type_traits>
#include <dune/common/forloop.hh> #include <dune/common/hybridutilities.hh>
#include <dune/common/unused.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/std/type_traits.hh> #include <dune/common/std/type_traits.hh>
#include <dune/common/std/utility.hh> #include <dune/common/std/utility.hh>
...@@ -318,43 +316,6 @@ namespace Dune { ...@@ -318,43 +316,6 @@ namespace Dune {
} }
}; };
namespace
{
template<int i, typename T1,typename F>
struct Visitor
{
static inline void visit(F& func, T1& t1)
{
func.visit(std::get<std::tuple_size<T1>::value-i>(t1));
Visitor<i-1,T1,F>::visit(func, t1);
}
};
template<typename T1,typename F>
struct Visitor<0,T1,F>
{
static inline void visit(F&, T1&)
{}
};
template<int i, typename T1, typename T2,typename F>
struct PairVisitor
{
static inline void visit(F& func, T1& t1, T2& t2)
{
func.visit(std::get<std::tuple_size<T1>::value-i>(t1), std::get<std::tuple_size<T2>::value-i>(t2));
PairVisitor<i-1,T1,T2,F>::visit(func, t1, t2);
}
};
template<typename T1, typename T2, typename F>
struct PairVisitor<0,T1,T2,F>
{
static inline void visit(F&, T1&, T2&)
{}
};
}
/** /**
* @brief Helper template which implements iteration over all storage * @brief Helper template which implements iteration over all storage
* elements in a std::tuple. * elements in a std::tuple.
...@@ -413,7 +374,8 @@ namespace Dune { ...@@ -413,7 +374,8 @@ namespace Dune {
template<class Functor> template<class Functor>
void apply(Functor& f) const void apply(Functor& f) const
{ {
Visitor<std::tuple_size<Tuple>::value,Tuple,Functor>::visit(f, t_); Hybrid::forEach(Std::make_index_sequence<std::tuple_size<Tuple>::value>{},
[&](auto i){f.visit(std::get<i>(t_));});
} }
private: private:
Tuple& t_; Tuple& t_;
...@@ -449,7 +411,8 @@ namespace Dune { ...@@ -449,7 +411,8 @@ namespace Dune {
template<class Functor> template<class Functor>
void apply(Functor& f) void apply(Functor& f)
{ {
PairVisitor<std::tuple_size<Tuple1>::value,Tuple1,Tuple2,Functor>::visit(f, t1_, t2_); Hybrid::forEach(Std::make_index_sequence<std::tuple_size<Tuple1>::value>{},
[&](auto i){f.visit(std::get<i>(t1_), std::get<i>(t2_));});
} }
private: private:
Tuple1& t1_; Tuple1& t1_;
...@@ -494,27 +457,14 @@ namespace Dune { ...@@ -494,27 +457,14 @@ namespace Dune {
/** /**
* @brief Deletes all objects pointed to in a std::tuple of pointers. * @brief Deletes all objects pointed to in a std::tuple of pointers.
*
* \warning Pointers cannot be set to nullptr, so calling the Deletor twice
* or accessing elements of a deleted std::tuple leads to unforeseeable results!
*/ */
template<class Tuple> template<class Tuple>
class PointerPairDeletor struct PointerPairDeletor
{ {
struct Deletor template<typename... Ts>
{ static void apply(std::tuple<Ts...>& t)
template<typename P>
void visit(const P& p)
{
delete p;
}
};
public:
static void apply(Tuple& t)
{ {
static Deletor deletor; Hybrid::forEach(t,[&](auto&& ti){delete ti; ti=nullptr;});
ForEachValue<Tuple>(t).apply(deletor);
} }
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment