diff --git a/dune/solvers/common/algorithm.hh b/dune/solvers/common/algorithm.hh index 546929ef4f89b265b7ffc5c881135505cc2fbd8d..52c6e57f8f2616a7d433263f10d8b277a6f9fdb4 100644 --- a/dune/solvers/common/algorithm.hh +++ b/dune/solvers/common/algorithm.hh @@ -86,6 +86,7 @@ void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) +// Implementation of hybridEquals namespace Imp { // Compute t1==t2 either statically or dynamically @@ -99,20 +100,80 @@ constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<0>) return t1==t2; } +} //end namespace Imp + +/** + * \brief Hybrid equality comparison + * + * If both types have a static member value, the result of comparing + * these is returned as std::integral_constant<bool, *>. Otherwise + * the result of a runtime comparison of t1 and t2 is directly returned. + */ +template<class T1, class T2> +constexpr auto hybridEquals(const T1& t1, const T2& t2) +{ + return Imp::hybridEquals(t1, t2, PriorityTag<1>()); +} + + + +// Implementation of hybridIf +namespace Imp { + +template<class IfFunc, class ElseFunc> +constexpr void hybridIf(std::true_type, IfFunc&& ifFunc, ElseFunc&& elseFunc) +{ + ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); +} + template<class IfFunc, class ElseFunc> -void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::false_type) +constexpr void hybridIf(std::false_type, IfFunc&& ifFunc, ElseFunc&& elseFunc) { elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); } template<class IfFunc, class ElseFunc> -void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc, std::true_type) +constexpr void hybridIf(const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) { - ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); + if (condition) + ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); + else + elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); } } //end namespace Imp +/** + * \brief Hybrid if + * + * This will call either ifFunc or elseFunc depending + * on the condition. In any case a single argument + * will be passed to the called function. This will always + * be the indentity function. Passing an expression through + * this function will lead to lazy evaluation. This way both + * 'branches' can contain expressions that are only valid + * within this branch if the condition is a std::integral_constant<bool,*>. + * + * In order to do this, the passed functors must have a single + * argument of type auto. + */ +template<class Condition, class IfFunc, class ElseFunc> +constexpr void hybridIf(const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) +{ + Imp::hybridIf(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc)); +} + +/** + * \brief Hybrid if + * + * This provides a hybridIf with empty else clause. + */ +template<class Condition, class IfFunc> +constexpr void hybridIf(const Condition& condition, IfFunc&& ifFunc) +{ + hybridIf(condition, std::forward<IfFunc>(ifFunc), [](auto&& i) {}); +} + // Everything in the next namespace block is just used to implement StaticSize, HasStaticSize, hybridSize @@ -266,90 +327,6 @@ void sparseRangeFor(Range&& range, F&& f) -/** - * \brief Hybrid equality comparison - * - * If both types have a static member value, the result of comparing - * these is returned as std::integral_constant<bool, *>. Otherwise - * the result of a runtime comparison of t1 and t2 is directly returned. - */ -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2) -{ - return Imp::hybridEquals(t1, t2, PriorityTag<1>()); -} - - -/** - * \brief Static if emulation - * - * This will call either ifFunc or elseFunc depending - * on the condition. In any case a single argument - * will be passed to the called function. This will always - * be the indentity function. Passing an expression through - * this function will lead to lazy evaluation. This way both - * 'branches' can contain expressions that are only valid - * within this branch. - */ -template<bool condition, class IfFunc, class ElseFunc> -void staticIf(IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - Imp::staticIf(std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc), std::integral_constant<bool, condition>()); -} - - - -namespace Imp { - -template<bool condition, class IfFunc, class ElseFunc> -void hybridIf(const std::integral_constant<bool, condition>&, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - staticIf<condition>(std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc)); -} - -template<class IfFunc, class ElseFunc> -void hybridIf(const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - if (condition) - ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); - else - elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); -} - -} // namespace Imp - - - -/** - * \brief Hybrid if - * - * This will call either ifFunc or elseFunc depending - * on the condition. In any case a single argument - * will be passed to the called function. This will always - * be the indentity function. Passing an expression through - * this function will lead to lazy evaluation. This way both - * 'branches' can contain expressions that are only valid - * within this branch if the condition is a std::integral_constant<bool,*>. - */ -template<class Condition, class IfFunc, class ElseFunc> -void hybridIf(const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - Imp::hybridIf(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc)); -} - - - -/** - * \brief Hybrid if - * - * This provides a hybridIf with empty else clause. - */ -template<class Condition, class IfFunc> -void hybridIf(const Condition& condition, IfFunc&& ifFunc) -{ - hybridIf(condition, std::forward<IfFunc>(ifFunc), [](auto&& i) {}); -} - } // namespace Solvers } // namespace Dune