diff --git a/octa/functional.h b/octa/functional.h index cd91eef..82cd656 100644 --- a/octa/functional.h +++ b/octa/functional.h @@ -349,6 +349,46 @@ namespace octa { typedef U second_argument_type; }; + template + struct IsValidFunctor { + static constexpr bool value = false; + }; + + template + struct IsValidFunctor, R(A...)> { + static constexpr bool value = false; + }; + + struct __OctaEmpty { + }; + + template + T func_to_functor(T &&f) { + return forward(f); + } + + template + auto func_to_functor(RR (T::*f)(AA...)) -> decltype(mem_fn(f)) { + return mem_fn(f); + } + + template + auto func_to_functor(RR (T::*f)(AA...) const) -> decltype(mem_fn(f)) { + return mem_fn(f); + } + + template + struct IsValidFunctor { + template + static decltype(func_to_functor(declval())(declval()...)) __octa_test(U *); + template + static __OctaEmpty __octa_test(...); + + static constexpr bool value = IsConvertible< + decltype(__octa_test(nullptr)), R + >::value; + }; + template struct Function: __OctaFunction { Function( ) noexcept { initialize_empty(); } @@ -364,7 +404,9 @@ namespace octa { } template - Function(T f) noexcept(__OctaFunctorInPlace::value) { + Function(T f, EnableIf::value, __OctaEmpty> + = __OctaEmpty()) + noexcept(__OctaFunctorInPlace::value) { if (func_is_null(f)) { initialize_empty(); return; @@ -441,21 +483,6 @@ namespace octa { static bool func_is_null(RR (T::* const &fptr)(AA...) const) { return fptr == nullptr; } - - template - T func_to_functor(T &&f) { - return forward(f); - } - - template - auto func_to_functor(RR (T::*f)(AA...)) -> decltype(mem_fn(f)) { - return mem_fn(f); - } - - template - auto func_to_functor(RR (T::*f)(AA...) const) -> decltype(mem_fn(f)) { - return mem_fn(f); - } }; template