for MapRange, specialize stored func in a few ways to avoid octa::Function (and thus avoid the significant overhead it brings)

This commit is contained in:
q66 2015-06-07 04:10:08 +01:00
parent 2652fe9242
commit 36d9a35066
2 changed files with 82 additions and 17 deletions

View file

@ -412,17 +412,81 @@ T foldr(R range, T init, F func) {
return init;
}
template<typename T, typename R>
namespace detail {
template<typename F>
struct MapLambdaArgs: MapLambdaArgs<decltype(&F::operator())> {};
template<typename C, typename R, typename A>
struct MapLambdaArgs<R(C::*)(A) const> {
typedef R Result;
typedef A Arg;
};
template<typename F>
using MapLambdaRet = typename MapLambdaArgs<F>::Result;
template<typename F>
using MapLambdaArg = typename MapLambdaArgs<F>::Arg;
template<typename T, typename F>
struct MapFuncTest {
template<typename FF>
static char test(MapLambdaRet<FF> (*)(MapLambdaArg<FF>));
template<typename FF>
static int test(...);
static constexpr bool value = (sizeof(test<F>(octa::declval<F>())) == 1) &&
octa::IsConvertible<
octa::RangeReference<T>,
decltype(octa::declval<F>()(octa::declval<
octa::RangeReference<T>
>()))
>::value;
};
template<typename T, typename R, typename F,
bool = octa::IsDefaultConstructible<F>::value &&
octa::IsMoveConstructible<F>::value
> struct MapFuncTypeObjBase {
typedef octa::Function<R(octa::RangeReference<T>)> Type;
};
template<typename T, typename R, typename F>
struct MapFuncTypeObjBase<T, R, F, true> {
typedef F Type;
};
template<typename T, typename R, typename F, bool = MapFuncTest<T, F>::value>
struct MapFuncTypeObj {
typedef typename MapFuncTypeObjBase<T, R, F>::Type Type;
};
template<typename T, typename R, typename F>
struct MapFuncTypeObj<T, R, F, true> {
typedef MapLambdaRet<F>(*Type)(MapLambdaArg<F>);
};
template<typename T, typename R, typename F, bool = octa::IsClass<F>::value>
struct MapFuncType {
typedef typename MapFuncTypeObj<T, R, F>::Type Type;
};
template<typename T, typename R, typename F>
struct MapFuncType<T, R, F, false> {
typedef F Type;
};
}
template<typename T, typename F, typename R>
struct MapRange: InputRange<
MapRange<T, R>, octa::RangeCategory<T>, R, R, octa::RangeSize<T>
MapRange<T, F, R>, octa::RangeCategory<T>, R, R, octa::RangeSize<T>
> {
private:
T p_range;
octa::Function<R(octa::RangeReference<T>)> p_func;
typename octa::detail::MapFuncType<T, R, F>::Type p_func;
public:
MapRange(): p_range(), p_func() {}
template<typename F>
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<T, R> slice(octa::RangeSize<T> start,
MapRange slice(octa::RangeSize<T> start,
octa::RangeSize<T> end) {
return MapRange<T, R>(p_range.slice(start, end), p_func);
return MapRange(p_range.slice(start, end), p_func);
}
};
@ -496,17 +560,18 @@ namespace detail {
= decltype(declval<F>()(octa::declval<octa::RangeReference<R>>()));
}
template<typename R, typename F>
MapRange<R, octa::detail::MapReturnType<R, F>> map(R range,
MapRange<R, F, octa::detail::MapReturnType<R, F>> map(R range,
F func) {
return octa::MapRange<R, octa::detail::MapReturnType<R, F>>(range,
return octa::MapRange<R, F, octa::detail::MapReturnType<R, F>>(range,
func);
}
template<typename T>
struct FilterRange: InputRange<
FilterRange<T>, octa::CommonType<octa::RangeCategory<T>,
octa::ForwardRangeTag>,
octa::ForwardRangeTag>,
octa::RangeValue<T>, octa::RangeReference<T>, octa::RangeSize<T>
> {
private:

View file

@ -135,7 +135,7 @@ template<typename T, size_t N> struct IsArray<T[N]>: True {};
/* is pointer */
namespace detail {
template<typename > struct IsPointerBase : False {};
template<typename > struct IsPointerBase : False {};
template<typename T> struct IsPointerBase<T *>: True {};
}
@ -144,12 +144,12 @@ struct IsPointer: octa::detail::IsPointerBase<RemoveCv<T>> {};
/* is lvalue reference */
template<typename > struct IsLvalueReference : False {};
template<typename > struct IsLvalueReference : False {};
template<typename T> struct IsLvalueReference<T &>: True {};
/* is rvalue reference */
template<typename > struct IsRvalueReference : False {};
template<typename > struct IsRvalueReference : False {};
template<typename T> struct IsRvalueReference<T &&>: True {};
/* is enum */
@ -174,13 +174,13 @@ namespace detail {
template<typename T> int function_test(...);
template<typename T> T &function_source(int);
template<typename T> FunctionTestDummy function_source(...);
template<typename T> FunctionTestDummy function_source(...);
template<typename T, bool = octa::IsClass<T>::value ||
octa::IsUnion<T>::value ||
octa::IsVoid<T>::value ||
octa::IsReference<T>::value ||
octa::IsNullPointer<T>::value
octa::IsUnion<T>::value ||
octa::IsVoid<T>::value ||
octa::IsReference<T>::value ||
octa::IsNullPointer<T>::value
> struct IsFunctionBase: IntegralConstant<bool,
sizeof(function_test<T>(function_source<T>(0))) == 1
> {};