diff --git a/octa/algorithm.h b/octa/algorithm.h index a1af894..a712fb8 100644 --- a/octa/algorithm.h +++ b/octa/algorithm.h @@ -412,17 +412,81 @@ T foldr(R range, T init, F func) { return init; } -template +namespace detail { + template + struct MapLambdaArgs: MapLambdaArgs {}; + + template + struct MapLambdaArgs { + typedef R Result; + typedef A Arg; + }; + + template + using MapLambdaRet = typename MapLambdaArgs::Result; + + template + using MapLambdaArg = typename MapLambdaArgs::Arg; + + template + struct MapFuncTest { + template + static char test(MapLambdaRet (*)(MapLambdaArg)); + template + static int test(...); + + static constexpr bool value = (sizeof(test(octa::declval())) == 1) && + octa::IsConvertible< + octa::RangeReference, + decltype(octa::declval()(octa::declval< + octa::RangeReference + >())) + >::value; + }; + + template::value && + octa::IsMoveConstructible::value + > struct MapFuncTypeObjBase { + typedef octa::Function)> Type; + }; + + template + struct MapFuncTypeObjBase { + typedef F Type; + }; + + template::value> + struct MapFuncTypeObj { + typedef typename MapFuncTypeObjBase::Type Type; + }; + + template + struct MapFuncTypeObj { + typedef MapLambdaRet(*Type)(MapLambdaArg); + }; + + template::value> + struct MapFuncType { + typedef typename MapFuncTypeObj::Type Type; + }; + + template + struct MapFuncType { + typedef F Type; + }; +} + +template struct MapRange: InputRange< - MapRange, octa::RangeCategory, R, R, octa::RangeSize + MapRange, octa::RangeCategory, R, R, octa::RangeSize > { private: T p_range; - octa::Function)> p_func; + typename octa::detail::MapFuncType::Type p_func; public: MapRange(): p_range(), p_func() {} - template MapRange(const T &range, const F &func): p_range(range), p_func(func) {} MapRange(const MapRange &it): @@ -485,9 +549,9 @@ public: return p_func(p_range[idx]); } - MapRange slice(octa::RangeSize start, + MapRange slice(octa::RangeSize start, octa::RangeSize end) { - return MapRange(p_range.slice(start, end), p_func); + return MapRange(p_range.slice(start, end), p_func); } }; @@ -496,17 +560,18 @@ namespace detail { = decltype(declval()(octa::declval>())); } + template -MapRange> map(R range, +MapRange> map(R range, F func) { - return octa::MapRange>(range, + return octa::MapRange>(range, func); } template struct FilterRange: InputRange< FilterRange, octa::CommonType, - octa::ForwardRangeTag>, + octa::ForwardRangeTag>, octa::RangeValue, octa::RangeReference, octa::RangeSize > { private: diff --git a/octa/type_traits.h b/octa/type_traits.h index f545748..e240713 100644 --- a/octa/type_traits.h +++ b/octa/type_traits.h @@ -135,7 +135,7 @@ template struct IsArray: True {}; /* is pointer */ namespace detail { - template struct IsPointerBase : False {}; + template struct IsPointerBase : False {}; template struct IsPointerBase: True {}; } @@ -144,12 +144,12 @@ struct IsPointer: octa::detail::IsPointerBase> {}; /* is lvalue reference */ -template struct IsLvalueReference : False {}; +template struct IsLvalueReference : False {}; template struct IsLvalueReference: True {}; /* is rvalue reference */ -template struct IsRvalueReference : False {}; +template struct IsRvalueReference : False {}; template struct IsRvalueReference: True {}; /* is enum */ @@ -174,13 +174,13 @@ namespace detail { template int function_test(...); template T &function_source(int); - template FunctionTestDummy function_source(...); + template FunctionTestDummy function_source(...); template::value || - octa::IsUnion::value || - octa::IsVoid::value || - octa::IsReference::value || - octa::IsNullPointer::value + octa::IsUnion::value || + octa::IsVoid::value || + octa::IsReference::value || + octa::IsNullPointer::value > struct IsFunctionBase: IntegralConstant(function_source(0))) == 1 > {};