diff --git a/dune/solvers/common/algorithm.hh b/dune/solvers/common/algorithm.hh index 4d20b2f58c104d5ce9c822cb1ae463b52734a80e..546929ef4f89b265b7ffc5c881135505cc2fbd8d 100644 --- a/dune/solvers/common/algorithm.hh +++ b/dune/solvers/common/algorithm.hh @@ -14,7 +14,7 @@ namespace Dune { namespace Solvers { -// Everything in the next namespace block is just used to implement integralRangeFor +// Implementation of integralRangeFor namespace Imp { template<class ST, ST begin, ST end> @@ -36,35 +36,27 @@ struct StaticForLoop<ST, end, end> {} }; - - -// Compute t1==t2 either statically or dynamically -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<1>) -> decltype(T1::value, T2::value, std::integral_constant<bool,T1::value == T2::value>()) -{ return {}; } - -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<0>) +// Overload for static ranges +template<class Index, class Begin, class End, class F, class... Args, + std::enable_if_t<IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value, int> = 0> +void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) { - return t1==t2; + static const Index begin_t = begin; + static const Index end_t = end; + StaticForLoop<Index, begin_t, end_t>::apply(std::forward<F>(f), std::forward<Args>(args)...); } -template<class IfFunc, class ElseFunc> -void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::false_type) +// Overload for dynamic ranges +template<class Index, class Begin, class End, class F, class... Args, + std::enable_if_t<not(IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value), int> = 0> +void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) { - elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); + for(Index i=begin; i != end; ++i) + f(i, std::forward<Args>(args)...); } -template<class IfFunc, class ElseFunc> -void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::true_type) -{ - ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); } -} //end namespace Imp - - - /** * \brief Hybrid for loop over integral range * @@ -81,52 +73,46 @@ void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::true_type) * * This is a hybrid for loop that can work on statically and dynamically * sized containers. The functor is called with index as first argument - * and all additional arguments. - * - * This is the static-size overload which is selected if begin and - * end are both static indices, i.e., integral constants. The loop - * body is called with std::integral_constant<Index,i> where i - * is the static index. + * and all additional arguments. If begin and end are both of type + * std::integral_constant<*,*> than the loop is static with indices + * of the form std::integral_constant<Index, *>, otherwise the loop + * is dynamic with indices type Index. */ -template<class Index, class Begin, class End, class F, class... Args, - std::enable_if_t<IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value, int> = 0> +template<class Index, class Begin, class End, class F, class... Args> void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) { - static const Index begin_t = begin; - static const Index end_t = end; - Imp::StaticForLoop<Index, begin_t, end_t>::apply(std::forward<F>(f), std::forward<Args>(args)...); + Imp::integralRangeFor<Index>(std::forward<Begin>(begin), std::forward<End>(end), std::forward<F>(f), std::forward<Args>(args)...); } -/** - * \brief Hybrid for loop over integral range - * - * \tparam Index Raw type of used indices - * \tparam Begin Type of begin index - * \tparam End Type of end index - * \tparam F Type of functor containing the loop body - * \tparam Args Types of further arguments to the loop body - * - * \param begin Initial index - * \param end One past last index - * \param f Functor to call in each loop instance - * \param args Additional arguments to be passed to the functor - * - * This is a hybrid for loop that can work on statically and dynamically - * sized containers. The functor is called with index as first argument - * and all additional arguments. - * - * This is the dynamic-size overload which is selected if either begin or - * end is a dynamic index, i.e., not an integral constant. The loop - * body is called with indices of type Index. - */ -template<class Index, class Begin, class End, class F, class... Args, - std::enable_if_t<not(IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value), int> = 0> -void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) + + +namespace Imp { + +// Compute t1==t2 either statically or dynamically +template<class T1, class T2> +constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<1>) -> decltype(T1::value, T2::value, std::integral_constant<bool,T1::value == T2::value>()) +{ return {}; } + +template<class T1, class T2> +constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<0>) { - for(Index i=begin; i != end; ++i) - f(i, std::forward<Args>(args)...); + return t1==t2; } +template<class IfFunc, class ElseFunc> +void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::false_type) +{ + elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); +} + +template<class IfFunc, class ElseFunc> +void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::true_type) +{ + ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); +} + +} //end namespace Imp + // Everything in the next namespace block is just used to implement StaticSize, HasStaticSize, hybridSize