diff --git a/dune/common/array.hh b/dune/common/array.hh index 8143996d2906a6c23bf7a96d4e08788b6be8867a..228c9ceed7ff31178f47c987b93c1c49e6556bbc 100644 --- a/dune/common/array.hh +++ b/dune/common/array.hh @@ -10,8 +10,8 @@ #include <array> -#include "dune/common/streamoperators.hh" -#include "dune/common/std/make_array.hh" +#include <dune/common/streamoperators.hh> +#include <dune/common/std/make_array.hh> namespace Dune { diff --git a/dune/common/forloop.hh b/dune/common/forloop.hh index b6e883b5e163b2fe60ac657d14de1ef3310d280b..02ec6c41cf4cb0a1443949b7ab92e4fbbedaed4e 100644 --- a/dune/common/forloop.hh +++ b/dune/common/forloop.hh @@ -6,6 +6,9 @@ #include <utility> +#include <dune/common/hybridutilities.hh> +#include <dune/common/std/utility.hh> + /** \file * \brief A static for loop for template meta-programming */ @@ -13,46 +16,6 @@ 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 * @brief A static loop using TMP * @@ -62,8 +25,8 @@ namespace Dune * which is called for i=first...last (first<=last are int template arguments). * A specialization for class template class Operation for i=first * or i=last is not required. The class Operation must provide a - * static void function apply(...). Arguments (as references) - * can be passed through the ForLoop to this function. + * static void function apply(...). Arguments are perfectly forwarded + * through the ForLoop to this function. * * It is possible to pass a subclass to the ForLoop * (since no specialization is needed). @@ -98,17 +61,18 @@ namespace Dune * } * }; * \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 > - class ForLoop - : public GenericForLoop< ForLoopHelper::Apply, Operation, first, last > + struct ForLoop { 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)...);}); + } }; } diff --git a/dune/common/streamoperators.hh b/dune/common/streamoperators.hh index 8af3adbbfe7b007a9a16c70f3138f9875bba0858..08a7b46cb30ed02b66dc06c3afe53de87bac70e9 100644 --- a/dune/common/streamoperators.hh +++ b/dune/common/streamoperators.hh @@ -9,10 +9,10 @@ */ #include <array> -#include <ostream> #include <tuple> -#include <dune/common/forloop.hh> +#include <dune/common/hybridutilities.hh> +#include <dune/common/std/utility.hh> 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 template<typename Stream, typename... Ts> inline Stream& operator<<(Stream& stream, const std::tuple<Ts...>& t) @@ -51,7 +28,8 @@ namespace Dune stream<<"["; 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<<"]"; @@ -62,7 +40,8 @@ namespace Dune template<typename Stream, typename... Ts> 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; } diff --git a/dune/common/test/CMakeLists.txt b/dune/common/test/CMakeLists.txt index 19b0bb396c3f3860b7cd0ccdd6e6c418ce581e71..fd227e79e3c1e2a535468813d4943515f753fe0d 100644 --- a/dune/common/test/CMakeLists.txt +++ b/dune/common/test/CMakeLists.txt @@ -202,7 +202,7 @@ dune_add_test(SOURCES testfloatcmp.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 LINK_LIBRARIES dunecommon diff --git a/dune/common/test/utilitytest.cc b/dune/common/test/utilitytest.cc index 1ce6b4bdccd28564a26fa45fbffc192ad3c6074c..3da070a72d8123d2cdb29b3f2f0618a4af31f0ed 100644 --- a/dune/common/test/utilitytest.cc +++ b/dune/common/test/utilitytest.cc @@ -30,27 +30,26 @@ struct Counter { int main(int, char**) { - 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; - if(std::get<0>(pointers)!=0) { + if(std::get<0>(pointers)!=nullptr) { std::cerr<<"First pointer not null"<<std::endl; ret=1; } - if(std::get<1>(pointers)!=0) { + if(std::get<1>(pointers)!=nullptr) { std::cerr<<"Second pointer not null"<<std::endl; ret=2; } - if(std::get<2>(pointers)!=0) { + if(std::get<2>(pointers)!=nullptr) { std::cerr<<"Third pointer not null"<<std::endl; ret=3; } - if(std::get<3>(pointers)!=0) { + if(std::get<3>(pointers)!=nullptr) { std::cerr<<"Fourth pointer not null"<<std::endl; ret=4; } @@ -70,15 +69,19 @@ int main(int, char**) Tuple1 t1(i,c,l,c); RefTuple1 refs(i, c, l, c); + +#if 0 DUNE_UNUSED RefTuple1 refs2(Dune::transformTuple<Dune::AddRefTypeEvaluator>(t1)); - PointerTuple1 pointers1 - (Dune::transformTuple<Dune::AddPtrTypeEvaluator>(refs)); + PointerTuple1 pointers1(Dune::transformTuple<Dune::AddPtrTypeEvaluator>(refs)); if(&i != std::get<0>(pointers1) || &c != std::get<1>(pointers1) || &l != std::get<2>(pointers1) || &c != std::get<3>(pointers1)) { std::cerr << "utilitytest: error: incorrect pointers in pointers1" << std::endl; 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)) { std::cerr<<"Length and size do not match!"<<std::endl; @@ -90,8 +93,6 @@ int main(int, char**) forEach.apply(count); std::cout << "Number of elements is: " << count.result_ << std::endl; - - Dune::ForEachValuePair<PointerTuple,PointerTuple1> foreach1(pointers, pointers1); foreach1.apply(count); @@ -105,6 +106,10 @@ int main(int, char**) typedef Dune::ForEachType<Eval,PointerTuple1>::Type ConvertedType DUNE_UNUSED; Dune::PointerPairDeletor<PointerTuple1>::apply(p); + if(p != PointerTuple1(nullptr,nullptr,nullptr,nullptr)){ + ret+=20; + std::cerr<<"PointerPairDeletor not working!"<<std::endl; + } return ret; } diff --git a/dune/common/tupleutility.hh b/dune/common/tupleutility.hh index b9fbe3f4910b7f0d301157e3380cc305d5b63349..296953f59a6113b258eeb854aac51f7db056eebe 100644 --- a/dune/common/tupleutility.hh +++ b/dune/common/tupleutility.hh @@ -5,12 +5,10 @@ #define DUNE_TUPLE_UTILITY_HH #include <cstddef> -#include <iostream> #include <tuple> +#include <type_traits> -#include <dune/common/forloop.hh> -#include <dune/common/unused.hh> -#include <dune/common/typetraits.hh> +#include <dune/common/hybridutilities.hh> #include <dune/common/std/type_traits.hh> #include <dune/common/std/utility.hh> @@ -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 * elements in a std::tuple. @@ -413,7 +374,8 @@ namespace Dune { template<class Functor> 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: Tuple& t_; @@ -449,7 +411,8 @@ namespace Dune { template<class Functor> 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: Tuple1& t1_; @@ -494,27 +457,14 @@ namespace Dune { /** * @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> - class PointerPairDeletor + struct PointerPairDeletor { - struct Deletor - { - template<typename P> - void visit(const P& p) - { - delete p; - } - }; - - public: - static void apply(Tuple& t) + template<typename... Ts> + static void apply(std::tuple<Ts...>& t) { - static Deletor deletor; - ForEachValue<Tuple>(t).apply(deletor); + Hybrid::forEach(t,[&](auto&& ti){delete ti; ti=nullptr;}); } };