diff --git a/octa/algorithm.h b/octa/algorithm.h index 9728e1c..32ddf74 100644 --- a/octa/algorithm.h +++ b/octa/algorithm.h @@ -414,19 +414,19 @@ T foldr(R range, T init, F func) { namespace detail { template - struct MapLambdaArgs: MapLambdaArgs {}; + struct MapLambdaTypes: MapLambdaTypes {}; template - struct MapLambdaArgs { + struct MapLambdaTypes { typedef R Result; typedef A Arg; }; template - using MapLambdaRet = typename MapLambdaArgs::Result; + using MapLambdaRet = typename MapLambdaTypes::Result; template - using MapLambdaArg = typename MapLambdaArgs::Arg; + using MapLambdaArg = typename MapLambdaTypes::Arg; template struct MapFuncTest { @@ -434,7 +434,6 @@ namespace detail { static char test(MapLambdaRet (*)(MapLambdaArg)); template static int test(...); - static constexpr bool value = (sizeof(test(octa::declval())) == 1); }; @@ -446,7 +445,7 @@ namespace detail { template struct MapFuncTypeObjBase { - typedef MapLambdaRet(*Type)(MapLambdaArg); + typedef MapLambdaRet (*Type)(MapLambdaArg); }; template()(octa::declval>())); } - template MapRange> map(R range, F func) { @@ -563,15 +561,67 @@ MapRange> map(R range, func); } -template +namespace detail { + template + struct FilterLambdaArg: FilterLambdaArg {}; + + template + struct FilterLambdaArg { + typedef A Type; + }; + + template + struct FilterPredTest { + template + static char test(bool (*)(typename FilterLambdaArg::Type)); + template + static int test(...); + static constexpr bool value = (sizeof(test(octa::declval())) == 1); + }; + + template::value + > struct FilterPredTypeObjBase { + typedef octa::Function)> Type; + }; + + template + struct FilterPredTypeObjBase { + typedef bool (*Type)(typename FilterLambdaArg::Type); + }; + + template::value && + octa::IsMoveConstructible::value + > struct FilterPredTypeObj { + typedef typename FilterPredTypeObjBase::Type Type; + }; + + template + struct FilterPredTypeObj { + typedef F Type; + }; + + template::value> + struct FilterPredType { + typedef F Type; + }; + + template + struct FilterPredType { + typedef typename FilterPredTypeObj::Type Type; + }; +} + +template struct FilterRange: InputRange< - FilterRange, octa::CommonType, + FilterRange, octa::CommonType, octa::ForwardRangeTag>, octa::RangeValue, octa::RangeReference, octa::RangeSize > { private: T p_range; - octa::Function)> p_pred; + typename octa::detail::FilterPredType::Type p_pred; void advance_valid() { while (!p_range.empty() && !p_pred(front())) p_range.pop_front(); @@ -631,9 +681,19 @@ public: octa::RangeReference front() const { return p_range.front(); } }; +namespace detail { + template using FilterPred + = octa::EnableIf()(octa::declval< + octa::RangeReference + >())), + bool + >::value, P>; +} + template -FilterRange filter(R range, P pred) { - return octa::FilterRange(range, pred); +FilterRange> filter(R range, P pred) { + return octa::FilterRange(range, pred); } } /* namespace octa */