diff --git a/doc/src/concepts.md b/doc/src/concepts.md index 2314b0e..1b27ac7 100644 --- a/doc/src/concepts.md +++ b/doc/src/concepts.md @@ -165,6 +165,79 @@ Given |---------------|--------------------------| | `f(identity)` | performs a function call | +Callable +-------- + +Is an object for which the `INVOKE` operation can be applied. + +#### Requirements: + +The type `T` satisfies `Callable` if + +Given + +* `f`, an object of type `const T` +* `Args...`, suitable list of argument types + +The following expressions must be valid: + +| Expression | Requirements | +|--------------------------------------|-------------------------------------------------------| +| `INVOKE(f, std::declval()...)` | the expression is well-formed in unevaluated context | + +where `INVOKE(f, x, xs...)` is defined as follows: + +* if `f` is a pointer to member function of class `T`: + + - If `std::is_base_of>()` is true, then `INVOKE(f, x, xs...)` is equivalent to `(x.*f)(xs...)` + - otherwise, if `std::decay_t` is a specialization of `std::reference_wrapper`, then `INVOKE(f, x, xs...)` is equivalent to `(x.get().*f)(xs...)` + - otherwise, if x does not satisfy the previous items, then `INVOKE(f, x, xs...)` is equivalent to `((*x).*f)(xs...)`. + +* otherwise, if `f` is a pointer to data member of class `T`: + + - If `std::is_base_of>()` is true, then `INVOKE(f, x)` is equivalent to `x.*f` + - otherwise, if `std::decay_t` is a specialization of `std::reference_wrapper`, then `INVOKE(f, x)` is equivalent to `x.get().*f` + - otherwise, if `x` does not satisfy the previous items, then `INVOKE(f, x)` is equivalent to `(*x).*f` + +* otherwise, `INVOKE(f, x, xs...)` is equivalent to `f(x, xs...)` + +UnaryCallable +------------- + +Is an object for which the `INVOKE` operation can be applied with one parameter. + +#### Requirements: + +* `Callable` + +Given + +* `f`, an object of type `const F` +* `arg`, a single argument + +| Expression | Requirements | +|------------------|-------------------------------------------------------| +| `INVOKE(f, arg)` | the expression is well-formed in unevaluated context | + +BinaryCallable +-------------------- + +Is an object for which the `INVOKE` operation can be applied with two parameters. + +#### Requirements: + +* `Callable` + +Given + +* `f`, an object of type `const F` +* `arg1`, a single argument +* `arg2`, a single argument + +| Expression | Requirements | +|-------------------------|-------------------------------------------------------| +| `INVOKE(f, arg1, arg2)` | the expression is well-formed in unevaluated context | + Metafunction ------------ diff --git a/fit/apply.h b/fit/apply.h index 133a62c..d45e70d 100644 --- a/fit/apply.h +++ b/fit/apply.h @@ -32,7 +32,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// /// Example /// ------- @@ -52,14 +52,117 @@ #include #include + namespace fit { namespace detail { +#if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE +struct apply_mem_fn +{ + template + struct convertible_args; + + template + struct is_convertible_args; + + template + struct is_convertible_args, convertible_args> + : and_...> + {}; + +#define FIT_APPLY_MEM_FN_CALL(cv) \ + template ::type>, \ + is_convertible_args, convertible_args> \ + >::value>::type> \ + constexpr R operator()(R (Base::*mf)(Ts...) cv, Derived&& ref, Us &&... xs) const \ + { \ + return (fit::forward(ref).*mf)(fit::forward(xs)...); \ + } + FIT_APPLY_MEM_FN_CALL() + FIT_APPLY_MEM_FN_CALL(const) + FIT_APPLY_MEM_FN_CALL(volatile) + FIT_APPLY_MEM_FN_CALL(const volatile) +}; + +struct apply_mem_data +{ + template ::type>::value + )>::type> + constexpr R operator()(R Base::*pmd, Derived&& ref) const + { + return fit::forward(ref).*pmd; + } +}; + +template())> +struct apply_deref +{ typedef U type; }; + +#endif struct apply_f { +#if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE + template::type>::value + )>::type> + constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_fn, id_, id_, id_...) + operator()(F&& f, T&& obj, Ts&&... xs) const FIT_SFINAE_MANUAL_RETURNS + ( + apply_mem_fn()(f, fit::forward(obj), fit::forward(xs)...) + ); + + template::type, class=typename std::enable_if<( + std::is_member_function_pointer::type>::value + )>::type> + constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_fn, id_, id_, id_...) + operator()(F&& f, T&& obj, Ts&&... xs) const FIT_SFINAE_MANUAL_RETURNS + ( + apply_mem_fn()(f, *fit::forward(obj), fit::forward(xs)...) + ); + + template::type>::value + )>::type> + constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_data, id_, id_) + operator()(F&& f, T&& obj) const FIT_SFINAE_MANUAL_RETURNS + ( + apply_mem_data()(f, fit::forward(obj)) + ); + + template::type, class=typename std::enable_if<( + std::is_member_object_pointer::type>::value + )>::type> + constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_data, id_, id_) + operator()(F&& f, T&& obj) const FIT_SFINAE_MANUAL_RETURNS + ( + apply_mem_data()(f, *fit::forward(obj)) + ); + +#else + + template + constexpr auto operator()(T Base::*pmd, Derived&& ref) const + FIT_RETURNS(fit::forward(ref).*pmd); + + template + constexpr auto operator()(PMD&& pmd, Pointer&& ptr) const + FIT_RETURNS((*fit::forward(ptr)).*fit::forward(pmd)); + + template + constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const + FIT_RETURNS((fit::forward(ref).*pmf)(fit::forward(args)...)); + + template + constexpr auto operator()(PMF&& pmf, Pointer&& ptr, Args&&... args) const + FIT_RETURNS(((*fit::forward(ptr)).*fit::forward(pmf))(fit::forward(args)...)); + +#endif template - constexpr FIT_SFINAE_RESULT(F, id_...) operator()(F&& f, Ts&&... xs) const FIT_SFINAE_RETURNS + constexpr FIT_SFINAE_RESULT(F, id_...) + operator()(F&& f, Ts&&... xs) const FIT_SFINAE_RETURNS ( f(fit::forward(xs)...) ); diff --git a/fit/apply_eval.h b/fit/apply_eval.h index 8d90547..6395782 100644 --- a/fit/apply_eval.h +++ b/fit/apply_eval.h @@ -34,7 +34,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// /// Ts must be: /// @@ -57,6 +57,7 @@ #include #include #include +#include #include #ifndef FIT_NO_ORDERD_BRACE_INIT @@ -95,7 +96,7 @@ struct eval_helper R result; template - constexpr eval_helper(const F& f, Ts&&... xs) : result(f(fit::forward(xs)...)) + constexpr eval_helper(const F& f, Ts&&... xs) : result(apply(f, fit::forward(xs)...)) {} constexpr R get_result() @@ -109,7 +110,7 @@ struct eval_helper { int x; template - constexpr eval_helper(const F& f, Ts&&... xs) : x(f(fit::forward(xs)...), 0) + constexpr eval_helper(const F& f, Ts&&... xs) : x(apply(f, fit::forward(xs)...), 0) {} }; #endif @@ -117,7 +118,7 @@ struct eval_helper struct apply_eval_f { template()(fit::eval(std::declval())...) + apply(std::declval(), fit::eval(std::declval())...) ), class=typename std::enable_if<(!std::is_void::value)>::type > @@ -134,7 +135,7 @@ struct apply_eval_f } template()(fit::eval(std::declval())...) + apply(std::declval(), fit::eval(std::declval())...) ), class=typename std::enable_if<(std::is_void::value)>::type > diff --git a/fit/by.h b/fit/by.h index a5b76cc..91f845c 100644 --- a/fit/by.h +++ b/fit/by.h @@ -43,12 +43,12 @@ /// /// Projection must be: /// -/// * [UnaryFunctionObject](concepts.md#unaryfunctionobject) +/// * [UnaryCallable](concepts.md#unarycallable) /// * MoveConstructible /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -60,14 +60,14 @@ /// {} /// int x; /// }; -/// assert(fit::by(std::mem_fn(&foo::x), _ + _)(foo(1), foo(2)) == 3); +/// assert(fit::by(&foo::x, _ + _)(foo(1), foo(2)) == 3); /// #include #include -#include +#include #include #include #include @@ -160,17 +160,17 @@ template struct by_adaptor; template -struct by_adaptor : Projection, F +struct by_adaptor : detail::callable_base, detail::callable_base { typedef by_adaptor fit_rewritable_tag; template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } template - constexpr const Projection& base_projection(Ts&&... xs) const + constexpr const detail::callable_base& base_projection(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -182,51 +182,51 @@ struct by_adaptor : Projection, F { template struct of - : Failure::template of()(std::declval()))...> + : Failure::template of>()(std::declval()))...> {}; }; }; struct failure - : failure_map + : failure_map> {}; - FIT_INHERIT_DEFAULT(by_adaptor, Projection, F) + FIT_INHERIT_DEFAULT(by_adaptor, detail::callable_base, F) - template + template), FIT_ENABLE_IF_CONVERTIBLE(G, detail::callable_base)> constexpr by_adaptor(P&& p, G&& f) - : Projection(fit::forward

(p)), F(fit::forward(f)) + : detail::callable_base(fit::forward

(p)), detail::callable_base(fit::forward(f)) {} FIT_RETURNS_CLASS(by_adaptor); template - constexpr FIT_SFINAE_RESULT(const F&, result_of>...) + constexpr FIT_SFINAE_RESULT(const detail::callable_base&, result_of&, id_>...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( detail::by_eval( - FIT_MANGLE_CAST(const Projection&)(FIT_CONST_THIS->base_projection(xs...)), - FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)), + FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_projection(xs...)), + FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...)), fit::forward(xs)... ) ); }; template -struct by_adaptor : Projection +struct by_adaptor : detail::callable_base { typedef by_adaptor fit_rewritable1_tag; template - constexpr const Projection& base_projection(Ts&&... xs) const + constexpr const detail::callable_base& base_projection(Ts&&... xs) const { return always_ref(*this)(xs...); } - FIT_INHERIT_DEFAULT(by_adaptor, Projection) + FIT_INHERIT_DEFAULT(by_adaptor, detail::callable_base) - template + template)> constexpr by_adaptor(P&& p) - : Projection(fit::forward

(p)) + : detail::callable_base(fit::forward

(p)) {} FIT_RETURNS_CLASS(by_adaptor); diff --git a/fit/capture.h b/fit/capture.h index 7af23de..fb8c0bd 100644 --- a/fit/capture.h +++ b/fit/capture.h @@ -8,7 +8,7 @@ #ifndef FIT_GUARD_CAPTURE_H #define FIT_GUARD_CAPTURE_H -#include +#include #include #include #include @@ -67,14 +67,14 @@ namespace fit { namespace detail { template -struct capture_invoke : F, Pack +struct capture_invoke : detail::callable_base, Pack { typedef capture_invoke fit_rewritable1_tag; template - constexpr capture_invoke(X&& x, Y&& y) : F(fit::forward(x)), Pack(fit::forward(y)) + constexpr capture_invoke(X&& x, Y&& y) : detail::callable_base(fit::forward(x)), Pack(fit::forward(y)) {} template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -108,7 +108,7 @@ struct capture_invoke : F, Pack }; struct failure - : failure_map + : failure_map> {}; FIT_RETURNS_CLASS(capture_invoke); @@ -120,7 +120,7 @@ struct capture_invoke : F, Pack id_, result_of...> >::type, - id_ + id_&&> ) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( @@ -129,7 +129,7 @@ struct capture_invoke : F, Pack FIT_MANGLE_CAST(const Pack&)(FIT_CONST_THIS->get_pack(xs...)), fit::pack_forward(fit::forward(xs)...) ) - (FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->base_function(xs...))) + (FIT_RETURNS_C_CAST(detail::callable_base&&)(FIT_CONST_THIS->base_function(xs...))) ); }; diff --git a/fit/combine.h b/fit/combine.h index c3ca48f..decc004 100644 --- a/fit/combine.h +++ b/fit/combine.h @@ -34,7 +34,7 @@ /// /// F and Gs must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -49,7 +49,7 @@ #include #include -#include +#include #include namespace fit { namespace detail { @@ -106,9 +106,9 @@ struct combine_adaptor_base, F, Gs...> template struct combine_adaptor -: detail::combine_adaptor_base::type, F, Gs...> +: detail::combine_adaptor_base::type, detail::callable_base, detail::callable_base...> { - typedef detail::combine_adaptor_base::type, F, Gs...> base_type; + typedef detail::combine_adaptor_base::type, detail::callable_base, detail::callable_base...> base_type; FIT_INHERIT_CONSTRUCTOR(combine_adaptor, base_type) }; diff --git a/fit/compose.h b/fit/compose.h index a703357..99380b3 100644 --- a/fit/compose.h +++ b/fit/compose.h @@ -36,7 +36,7 @@ /// /// Fs must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -64,7 +64,7 @@ /// assert(r == 4); /// -#include +#include #include #include #include @@ -97,30 +97,30 @@ struct compose_kernel : detail::compressed_pair } template -struct compose_adaptor : detail::compose_kernel +struct compose_adaptor : detail::compose_kernel, FIT_JOIN(compose_adaptor, detail::callable_base...)> { typedef compose_adaptor fit_rewritable_tag; - typedef FIT_JOIN(compose_adaptor, Fs...) tail; - typedef detail::compose_kernel base_type; + typedef FIT_JOIN(compose_adaptor, detail::callable_base...) tail; + typedef detail::compose_kernel, tail> base_type; FIT_INHERIT_DEFAULT(compose_adaptor, base_type) - template + template), FIT_ENABLE_IF_CONSTRUCTIBLE(tail, Xs...)> constexpr compose_adaptor(X&& f1, Xs&& ... fs) : base_type(fit::forward(f1), tail(fit::forward(fs)...)) {} }; template -struct compose_adaptor : F +struct compose_adaptor : detail::callable_base { typedef compose_adaptor fit_rewritable_tag; - FIT_INHERIT_DEFAULT(compose_adaptor, F) + FIT_INHERIT_DEFAULT(compose_adaptor, detail::callable_base) - template + template)> constexpr compose_adaptor(X&& f1) - : F(fit::forward(f1)) + : detail::callable_base(fit::forward(f1)) {} }; diff --git a/fit/compress.h b/fit/compress.h index 6498a81..cc5d94e 100644 --- a/fit/compress.h +++ b/fit/compress.h @@ -44,11 +44,11 @@ /// /// State must be: /// -/// * MoveConstructible +/// * CopyConstructible /// /// F must be: /// -/// * [BinaryFunctionObject](concepts.md#binaryfunctionobject) +/// * [BinaryCallable](concepts.md#binarycallable) /// * MoveConstructible /// /// Example @@ -65,7 +65,7 @@ /// assert(fit::compress(max_f())(2, 3, 4, 5) == 5); /// -#include +#include #include #include #include @@ -95,30 +95,30 @@ struct v_fold template struct compress_adaptor -: detail::compressed_pair +: detail::compressed_pair, State> { - typedef detail::compressed_pair base_type; + typedef detail::compressed_pair, State> base_type; FIT_INHERIT_CONSTRUCTOR(compress_adaptor, base_type) template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return this->first(xs...); } template - constexpr const State& get_state(Ts&&... xs) const + constexpr State get_state(Ts&&... xs) const { return this->second(xs...); } template - constexpr FIT_SFINAE_RESULT(detail::v_fold, id_, id_, id_...) + constexpr FIT_SFINAE_RESULT(detail::v_fold, id_&>, id_, id_...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( detail::v_fold()( - FIT_MANGLE_CAST(const F&)(this->base_function(xs...)), - FIT_MANGLE_CAST(State&&)(fit::move(this->get_state(xs...))), + FIT_MANGLE_CAST(const detail::callable_base&)(this->base_function(xs...)), + FIT_MANGLE_CAST(State)(this->get_state(xs...)), fit::forward(xs)... ) ) @@ -127,22 +127,22 @@ struct compress_adaptor template struct compress_adaptor -: F +: detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(compress_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(compress_adaptor, detail::callable_base) template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } template - constexpr FIT_SFINAE_RESULT(detail::v_fold, id_, id_...) + constexpr FIT_SFINAE_RESULT(detail::v_fold, id_&>, id_...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( detail::v_fold()( - FIT_MANGLE_CAST(const F&)(this->base_function(xs...)), + FIT_MANGLE_CAST(const detail::callable_base&)(this->base_function(xs...)), fit::forward(xs)... ) ) diff --git a/fit/conditional.h b/fit/conditional.h index 12633da..19ed67a 100644 --- a/fit/conditional.h +++ b/fit/conditional.h @@ -35,7 +35,7 @@ /// /// Fs must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -68,7 +68,7 @@ /// to how the function is chosen. #include -#include +#include #include #include #include @@ -106,14 +106,14 @@ struct conditional_adaptor_base : conditional_adaptor_base, c }; template -struct conditional_adaptor_base : F +struct conditional_adaptor_base : detail::callable_base { - typedef F base; + typedef detail::callable_base base; - FIT_INHERIT_CONSTRUCTOR(conditional_adaptor_base, F); + FIT_INHERIT_CONSTRUCTOR(conditional_adaptor_base, detail::callable_base); template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -121,10 +121,10 @@ struct conditional_adaptor_base : F FIT_RETURNS_CLASS(conditional_adaptor_base); template - constexpr FIT_SFINAE_RESULT(const F&, id_...) + constexpr FIT_SFINAE_RESULT(const detail::callable_base&, id_...) operator()(rank, Ts&&... xs) const FIT_SFINAE_RETURNS ( - (FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward(xs)...) + (FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward(xs)...) ); }; diff --git a/fit/decorate.h b/fit/decorate.h index db5d3b9..93bfe4d 100644 --- a/fit/decorate.h +++ b/fit/decorate.h @@ -32,7 +32,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include @@ -125,22 +125,22 @@ struct decoration } template - constexpr decorator_invoke operator()(F f) const + constexpr decorator_invoke, T, D> operator()(F f) const { - return decorator_invoke(fit::move(f), this->get_data(f), this->get_decorator(f)); + return decorator_invoke, T, D>(fit::move(f), this->get_data(f), this->get_decorator(f)); } }; } template -struct decorate_adaptor : F +struct decorate_adaptor : detail::callable_base { typedef decorate_adaptor fit_rewritable1_tag; - FIT_INHERIT_CONSTRUCTOR(decorate_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(decorate_adaptor, detail::callable_base) template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -148,9 +148,9 @@ struct decorate_adaptor : F // TODO: Add predicate for constraints template - constexpr detail::decoration operator()(T x) const + constexpr detail::decoration> operator()(T x) const { - return detail::decoration(fit::move(x), this->base_function(x)); + return detail::decoration>(fit::move(x), this->base_function(x)); } }; diff --git a/fit/detail/callable_base.h b/fit/detail/callable_base.h new file mode 100644 index 0000000..d362b64 --- /dev/null +++ b/fit/detail/callable_base.h @@ -0,0 +1,69 @@ +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + callable_base.h + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#ifndef FIT_GUARD_CALLABLE_BASE_H +#define FIT_GUARD_CALLABLE_BASE_H + +#include +#include +#include + +#ifndef FIT_HAS_TEMPLATE_ALIAS +#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) +#define FIT_HAS_TEMPLATE_ALIAS 0 +#else +#define FIT_HAS_TEMPLATE_ALIAS 1 +#endif +#endif + +namespace fit { namespace detail { + +template +struct non_class_function +{ + F f; + FIT_DELGATE_CONSTRUCTOR(non_class_function, F, f) + + template + constexpr FIT_SFINAE_RESULT(apply_f, id_, id_...) + operator()(Ts&&... xs) const FIT_SFINAE_RETURNS + ( + fit::apply(f, fit::forward(xs)...) + ); +}; + +#if FIT_HAS_TEMPLATE_ALIAS +template +using callable_base = typename std::conditional<(std::is_class::value), F, non_class_function>::type; +#else + +template +struct callable_base_type +: std::conditional<(std::is_class::value), F, non_class_function> +{}; + +template +struct callable_base +: callable_base_type::type +{ + typedef typename callable_base_type::type base; + FIT_INHERIT_CONSTRUCTOR(callable_base, base) +}; + +template +struct callable_base> +: callable_base +{ + typedef callable_base base; + FIT_INHERIT_CONSTRUCTOR(callable_base, base) +}; + +#endif + +}} + +#endif \ No newline at end of file diff --git a/fit/detail/can_be_called.h b/fit/detail/can_be_called.h new file mode 100644 index 0000000..a6d5f6d --- /dev/null +++ b/fit/detail/can_be_called.h @@ -0,0 +1,111 @@ +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + can_be_called.h + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#ifndef FIT_GUARD_CAN_BE_CALLED_H +#define FIT_GUARD_CAN_BE_CALLED_H + +#include +#include +#include + +namespace fit { namespace detail { + +#if FIT_NO_EXPRESSION_SFINAE +struct dont_care +{ + dont_care(...); +}; + +template +struct never_care +{ + typedef dont_care type; +}; + +struct cant_be_called_type +{}; + +struct no_type +{}; + +template::type>::type> +struct is_callable_wrapper_base +: std::conditional::value, U, no_type> +{}; + +template +struct is_callable_wrapper : is_callable_wrapper_base::type +{ + is_callable_wrapper(); + typedef cant_be_called_type const &(*pointer_to_function)(typename never_care::type...); + operator pointer_to_function() const; +}; + +template +struct not_ +: std::integral_constant +{}; + +template +struct can_be_called +: not_()(std::declval()...) +)>::type>> +{}; + +template +struct check_args; + +template +struct check_args +: and_...> +{}; + +template +struct can_be_called +: std::conditional, + std::false_type +>::type +{}; + +template +struct can_be_called +: std::conditional, + std::false_type +>::type +{}; + +#else + +template +struct callable_args +{}; + +template +struct can_be_called_impl +: std::false_type +{}; + +template +struct can_be_called_impl, typename detail::holder< + decltype( std::declval()(std::declval()...) ) +>::type> +: std::true_type +{}; + +template +struct can_be_called +: can_be_called_impl> +{}; + +#endif + +}} + +#endif diff --git a/fit/detail/result_of.h b/fit/detail/result_of.h index 8ba29fd..916b03c 100644 --- a/fit/detail/result_of.h +++ b/fit/detail/result_of.h @@ -21,9 +21,9 @@ #if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE -#include -#include +#include #include +#include namespace fit { namespace detail { @@ -34,7 +34,7 @@ template struct result_of_impl< F, holder, - typename std::enable_if::value>::type + typename std::enable_if::value>::type > { typedef decltype(std::declval()(std::declval()...)) type; diff --git a/fit/fix.h b/fit/fix.h index 5690d29..93a9048 100644 --- a/fit/fix.h +++ b/fit/fix.h @@ -37,7 +37,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -48,7 +48,7 @@ /// #include -#include +#include #include #include #include @@ -71,12 +71,12 @@ namespace fit { namespace detail{ template -struct fix_adaptor_base : F +struct fix_adaptor_base : detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(fix_adaptor_base, F); + FIT_INHERIT_CONSTRUCTOR(fix_adaptor_base, detail::callable_base); template - FIT_FIX_CONSTEXPR const F& base_function(Ts&&... xs) const + FIT_FIX_CONSTEXPR const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -100,17 +100,17 @@ struct fix_adaptor_base : F }; struct failure - : failure_map + : failure_map> {}; FIT_RETURNS_CLASS(fix_adaptor_base); template - FIT_FIX_CONSTEXPR FIT_SFINAE_RESULT(const F&, id_, id_...) + FIT_FIX_CONSTEXPR FIT_SFINAE_RESULT(const detail::callable_base&, id_, id_...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( - FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)) + FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...)) (FIT_MANGLE_CAST(const Derived&)(FIT_CONST_THIS->derived_function(xs...)), fit::forward(xs)...) ); }; diff --git a/fit/flip.h b/fit/flip.h index e32f0a4..104bc13 100644 --- a/fit/flip.h +++ b/fit/flip.h @@ -32,7 +32,7 @@ /// /// F must be: /// -/// * [BinaryFunctionObject](concepts.md#binaryfunctionobject) +/// * [BinaryCallable](concepts.md#binarycallable) /// * MoveConstructible /// /// Example @@ -42,7 +42,7 @@ /// assert(r == 3); /// -#include +#include #include #include #include @@ -50,10 +50,10 @@ namespace fit { template -struct flip_adaptor : F +struct flip_adaptor : detail::callable_base { typedef flip_adaptor fit_rewritable1_tag; - FIT_INHERIT_CONSTRUCTOR(flip_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(flip_adaptor, detail::callable_base); template constexpr const F& base_function(Ts&&... xs) const @@ -74,16 +74,16 @@ struct flip_adaptor : F }; struct failure - : failure_map + : failure_map> {}; FIT_RETURNS_CLASS(flip_adaptor); template - constexpr FIT_SFINAE_RESULT(const F&, id_, id_, id_...) + constexpr FIT_SFINAE_RESULT(const detail::callable_base&, id_, id_, id_...) operator()(T&& x, U&& y, Ts&&... xs) const FIT_SFINAE_RETURNS ( - (FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...))) + (FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...))) (fit::forward(y), fit::forward(x), fit::forward(xs)...) ); }; diff --git a/fit/flow.h b/fit/flow.h index 5641397..63899c5 100644 --- a/fit/flow.h +++ b/fit/flow.h @@ -36,7 +36,7 @@ /// /// Fs must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -64,7 +64,7 @@ /// assert(r == 4); /// -#include +#include #include #include #include @@ -77,20 +77,20 @@ namespace fit { namespace detail { template -struct flow_kernel : detail::compressed_pair +struct flow_kernel : detail::compressed_pair, detail::callable_base> { - typedef detail::compressed_pair base_type; + typedef detail::compressed_pair, detail::callable_base> base_type; FIT_INHERIT_CONSTRUCTOR(flow_kernel, base_type) FIT_RETURNS_CLASS(flow_kernel); template - constexpr FIT_SFINAE_RESULT(const F2&, result_of...>) + constexpr FIT_SFINAE_RESULT(const detail::callable_base&, result_of&, id_...>) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( - FIT_MANGLE_CAST(const F2&)(FIT_CONST_THIS->second(xs...))( - FIT_MANGLE_CAST(const F1&)(FIT_CONST_THIS->first(xs...))(fit::forward(xs)...) + FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->second(xs...))( + FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->first(xs...))(fit::forward(xs)...) ) ); }; @@ -112,14 +112,14 @@ struct flow_adaptor : detail::flow_kernel }; template -struct flow_adaptor : F +struct flow_adaptor : detail::callable_base { typedef flow_adaptor fit_rewritable_tag; - FIT_INHERIT_DEFAULT(flow_adaptor, F) + FIT_INHERIT_DEFAULT(flow_adaptor, detail::callable_base) - template + template)> constexpr flow_adaptor(X&& f1) - : F(fit::forward(f1)) + : detail::callable_base(fit::forward(f1)) {} }; diff --git a/fit/if.h b/fit/if.h index 2689acd..7785174 100644 --- a/fit/if.h +++ b/fit/if.h @@ -36,7 +36,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -58,7 +58,7 @@ /// #include -#include +#include #include #include #include @@ -74,9 +74,9 @@ struct if_depend {}; template -struct if_adaptor : F +struct if_adaptor : detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(if_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(if_adaptor, detail::callable_base) }; template diff --git a/fit/indirect.h b/fit/indirect.h index 9dc82bf..0f4366b 100644 --- a/fit/indirect.h +++ b/fit/indirect.h @@ -61,7 +61,7 @@ #include namespace fit { - +// TODO: Support non-classes as well template struct indirect_adaptor : F { diff --git a/fit/infix.h b/fit/infix.h index 59e2347..d4b439a 100644 --- a/fit/infix.h +++ b/fit/infix.h @@ -34,7 +34,7 @@ /// /// F must be: /// -/// * [BinaryFunctionObject](concepts.md#binaryfunctionobject) +/// * [BinaryCallable](concepts.md#binarycallable) /// * MoveConstructible /// /// Example @@ -55,7 +55,7 @@ /// #include -#include +#include #include #include #include @@ -105,19 +105,19 @@ constexpr postfix_adaptor make_postfix_adaptor(T&& x, F f) } template -struct infix_adaptor : F +struct infix_adaptor : detail::callable_base { typedef infix_adaptor fit_rewritable1_tag; - FIT_INHERIT_CONSTRUCTOR(infix_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(infix_adaptor, detail::callable_base); template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } template - constexpr const F& infix_base_function(Ts&&... xs) const + constexpr const detail::callable_base& infix_base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -127,7 +127,7 @@ struct infix_adaptor : F template constexpr auto operator()(Ts&&... xs) const FIT_RETURNS ( - (FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward(xs)...) + (FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward(xs)...) ); }; diff --git a/fit/is_callable.h b/fit/is_callable.h index b3d4548..86bbea9 100644 --- a/fit/is_callable.h +++ b/fit/is_callable.h @@ -14,9 +14,15 @@ /// Description /// ----------- /// -/// The `is_callable` metafunction checks if the function object is callable with +/// The `is_callable` metafunction checks if the function is callable with /// certain parameters. /// +/// Requirements +/// ------------ +/// +/// F must be: +/// +/// * [Callable](concepts.md#callable) /// /// Synopsis /// -------- @@ -36,108 +42,17 @@ /// static_assert(is_callable(), "Not callable"); /// -#include -#include -#include -#include -#include + +#include +#include namespace fit { -#if FIT_NO_EXPRESSION_SFINAE -namespace detail { - -struct dont_care -{ - dont_care(...); -}; - -template -struct never_care -{ - typedef dont_care type; -}; - -struct cant_be_called_type -{}; - -template -struct is_callable_wrapper : std::remove_cv::type>::type -{ - is_callable_wrapper(); - typedef cant_be_called_type const &(*pointer_to_function)(typename never_care::type...); - operator pointer_to_function() const; -}; - -template -struct not_ -: std::integral_constant -{}; - -template -struct can_be_called -: not_()(std::declval()...) -)>::type>> -{}; - -template -struct check_args; - -template -struct check_args -: and_...> -{}; - -template -struct can_be_called -: std::conditional, - std::false_type ->::type -{}; - -template -struct can_be_called -: std::conditional, - std::false_type ->::type -{}; -} - template struct is_callable -: detail::can_be_called +: detail::can_be_called {}; -#else -namespace detail { -template -struct callable_args -{}; - -template -struct is_callable_impl -: std::false_type -{}; - -template -struct is_callable_impl, typename detail::holder< - decltype( std::declval()(std::declval()...) ) ->::type> -: std::true_type -{}; -} - - -template -struct is_callable -: detail::is_callable_impl> -{}; - -#endif - } #endif diff --git a/fit/lazy.h b/fit/lazy.h index 855650a..b098381 100644 --- a/fit/lazy.h +++ b/fit/lazy.h @@ -36,7 +36,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -225,12 +225,12 @@ constexpr lazy_nullary_invoker make_lazy_nullary_invoker(F f) template -struct lazy_adaptor : F +struct lazy_adaptor : detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(lazy_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(lazy_adaptor, detail::callable_base); template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -240,7 +240,7 @@ struct lazy_adaptor : F template constexpr auto operator()(T x, Ts... xs) const FIT_RETURNS ( - fit::detail::make_lazy_invoker(FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->base_function(x, xs...)), + fit::detail::make_lazy_invoker(FIT_RETURNS_C_CAST(detail::callable_base&&)(FIT_CONST_THIS->base_function(x, xs...)), pack(fit::move(x), fit::move(xs)...)) ); @@ -248,7 +248,7 @@ struct lazy_adaptor : F template constexpr detail::lazy_nullary_invoker operator()() const { - return fit::detail::make_lazy_nullary_invoker((F&&)( + return fit::detail::make_lazy_nullary_invoker((detail::callable_base&&)( this->base_function(Unused()) )); } diff --git a/fit/match.h b/fit/match.h index 0a19dd0..64d8f58 100644 --- a/fit/match.h +++ b/fit/match.h @@ -30,7 +30,7 @@ /// /// Fs must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -62,6 +62,7 @@ /// #include +#include #include #include #include @@ -72,20 +73,20 @@ namespace fit { template struct match_adaptor; template -struct match_adaptor : F, match_adaptor +struct match_adaptor : detail::callable_base, match_adaptor { typedef match_adaptor base; typedef match_adaptor fit_rewritable_tag; struct failure - : failure_for + : failure_for, Fs...> {}; - FIT_INHERIT_DEFAULT(match_adaptor, F, base); + FIT_INHERIT_DEFAULT(match_adaptor, detail::callable_base, base); - template + template), FIT_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)> constexpr match_adaptor(X&& f1, Xs&& ... fs) - : F(fit::forward(f1)), base(fit::forward(fs)...) + : detail::callable_base(fit::forward(f1)), base(fit::forward(fs)...) {} using F::operator(); @@ -93,13 +94,13 @@ struct match_adaptor : F, match_adaptor }; template -struct match_adaptor : F +struct match_adaptor : detail::callable_base { - typedef F base; + typedef detail::callable_base base; typedef match_adaptor fit_rewritable_tag; using F::operator(); - FIT_INHERIT_CONSTRUCTOR(match_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(match_adaptor, detail::callable_base); }; FIT_DECLARE_STATIC_VAR(match, detail::make); diff --git a/fit/partial.h b/fit/partial.h index 611de5b..fd83d05 100644 --- a/fit/partial.h +++ b/fit/partial.h @@ -37,7 +37,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -173,13 +173,13 @@ struct partial_adaptor_base > type; }; -template -struct partial_adaptor_base +template +struct partial_adaptor_pack_base { typedef conditional_adaptor < F, - partial_adaptor_pack, F> + partial_adaptor_pack > type; }; @@ -214,14 +214,14 @@ struct partial_adaptor : detail::partial_adaptor_base::type, F, Pack }; template -struct partial_adaptor : detail::partial_adaptor_base::type +struct partial_adaptor : detail::partial_adaptor_pack_base, detail::callable_base>::type { - typedef typename detail::partial_adaptor_base::type base; + typedef typename detail::partial_adaptor_pack_base, detail::callable_base>::type base; typedef partial_adaptor fit_rewritable1_tag; template - constexpr const F& base_function(Ts&&...) const + constexpr const detail::callable_base& base_function(Ts&&...) const { return *this; } @@ -231,6 +231,7 @@ struct partial_adaptor : detail::partial_adaptor_base::type FIT_INHERIT_CONSTRUCTOR(partial_adaptor, base); }; + // Make partial_adaptor work with pipable_adaptor by removing its pipableness template struct partial_adaptor, void> diff --git a/fit/pipable.h b/fit/pipable.h index 30c3c6b..d0e0ebe 100644 --- a/fit/pipable.h +++ b/fit/pipable.h @@ -36,7 +36,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -145,14 +145,14 @@ constexpr auto operator|(A&& a, const pipe_closure& p) FIT_RETURNS template struct pipable_adaptor -: conditional_adaptor, F> > +: conditional_adaptor, detail::pipe_pack, detail::callable_base> > { - typedef conditional_adaptor, F> > base; + typedef conditional_adaptor, detail::pipe_pack, detail::callable_base> > base; typedef pipable_adaptor fit_rewritable_tag; FIT_INHERIT_CONSTRUCTOR(pipable_adaptor, base); - constexpr const F& base_function() const + constexpr const detail::callable_base& base_function() const { return *this; } diff --git a/fit/protect.h b/fit/protect.h index 3cc09e8..1b8486b 100644 --- a/fit/protect.h +++ b/fit/protect.h @@ -31,7 +31,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// @@ -44,11 +44,11 @@ namespace fit { template -struct protect_adaptor : F +struct protect_adaptor : detail::callable_base { typedef protect_adaptor fit_rewritable1_tag; template - constexpr protect_adaptor(Ts&&... xs) : F(fit::forward(xs)...) + constexpr protect_adaptor(Ts&&... xs) : detail::callable_base(fit::forward(xs)...) {} }; diff --git a/fit/result.h b/fit/result.h index 3a0cdad..d629e0d 100644 --- a/fit/result.h +++ b/fit/result.h @@ -31,7 +31,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -50,7 +50,7 @@ /// static_assert(std::is_same::value, "Not the same type"); /// -#include +#include #include #include #include @@ -58,18 +58,18 @@ namespace fit { template -struct result_adaptor : F +struct result_adaptor : detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(result_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base) typedef Result result_type; struct failure - : failure_for + : failure_for> {}; template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -82,14 +82,14 @@ struct result_adaptor : F }; template -struct result_adaptor : F +struct result_adaptor : detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(result_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base) typedef void result_type; template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } diff --git a/fit/reveal.h b/fit/reveal.h index b8b180d..e0b175d 100644 --- a/fit/reveal.h +++ b/fit/reveal.h @@ -32,7 +32,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -211,13 +212,13 @@ struct failure_for template struct reveal_adaptor -: detail::traverse_failure, F +: detail::traverse_failure>, detail::callable_base { typedef reveal_adaptor fit_rewritable1_tag; - using detail::traverse_failure::operator(); - using F::operator(); + using detail::traverse_failure>::operator(); + using detail::callable_base::operator(); - FIT_INHERIT_CONSTRUCTOR(reveal_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(reveal_adaptor, detail::callable_base); }; // Avoid double reveals, it causes problem on gcc 4.6 template diff --git a/fit/reverse_compress.h b/fit/reverse_compress.h index 1c47435..897429b 100644 --- a/fit/reverse_compress.h +++ b/fit/reverse_compress.h @@ -45,11 +45,11 @@ /// /// State must be: /// -/// * MoveConstructible +/// * CopyConstructible /// /// F must be: /// -/// * [BinaryFunctionObject](concepts.md#binaryfunctionobject) +/// * [BinaryCallable](concepts.md#binarycallable) /// * MoveConstructible /// /// Example @@ -66,7 +66,7 @@ /// assert(fit::reverse_compress(max_f())(2, 3, 4, 5) == 5); /// -#include +#include #include #include #include @@ -96,30 +96,30 @@ struct v_reverse_fold template struct reverse_compress_adaptor -: detail::compressed_pair +: detail::compressed_pair, State> { - typedef detail::compressed_pair base_type; + typedef detail::compressed_pair, State> base_type; FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, base_type) template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return this->first(xs...); } template - constexpr const State& get_state(Ts&&... xs) const + constexpr State get_state(Ts&&... xs) const { return this->second(xs...); } template - constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_, id_, id_...) + constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_&>, id_, id_...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( detail::v_reverse_fold()( - FIT_MANGLE_CAST(const F&)(this->base_function(xs...)), - FIT_MANGLE_CAST(State&&)(fit::move(this->get_state(xs...))), + FIT_MANGLE_CAST(const detail::callable_base&)(this->base_function(xs...)), + FIT_MANGLE_CAST(State)(this->get_state(xs...)), fit::forward(xs)... ) ) @@ -128,22 +128,22 @@ struct reverse_compress_adaptor template struct reverse_compress_adaptor -: F +: detail::callable_base { - FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, F) + FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, detail::callable_base) template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } template - constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_, id_...) + constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_&>, id_...) operator()(Ts&&... xs) const FIT_SFINAE_RETURNS ( detail::v_reverse_fold()( - FIT_MANGLE_CAST(const F&)(this->base_function(xs...)), + FIT_MANGLE_CAST(const detail::callable_base&)(this->base_function(xs...)), fit::forward(xs)... ) ) diff --git a/fit/rotate.h b/fit/rotate.h index 4134a05..bf135c6 100644 --- a/fit/rotate.h +++ b/fit/rotate.h @@ -33,7 +33,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -51,13 +51,13 @@ namespace fit { template -struct rotate_adaptor : F +struct rotate_adaptor : detail::callable_base { typedef rotate_adaptor fit_rewritable1_tag; - FIT_INHERIT_CONSTRUCTOR(rotate_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(rotate_adaptor, detail::callable_base); template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -75,16 +75,16 @@ struct rotate_adaptor : F }; struct failure - : failure_map + : failure_map> {}; FIT_RETURNS_CLASS(rotate_adaptor); template - constexpr FIT_SFINAE_RESULT(const F&, id_..., id_) + constexpr FIT_SFINAE_RESULT(const detail::callable_base&, id_..., id_) operator()(T&& x, Ts&&... xs) const FIT_SFINAE_RETURNS ( - (FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...))) + (FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(xs...))) (fit::forward(xs)..., fit::forward(x)) ); }; diff --git a/fit/tap.h b/fit/tap.h index 315e69c..8f1355a 100644 --- a/fit/tap.h +++ b/fit/tap.h @@ -30,7 +30,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [UnaryCallable](concepts.md#unarycallable) /// /// Example /// ------- @@ -51,6 +51,7 @@ /// #include +#include #include namespace fit { namespace detail { @@ -60,7 +61,7 @@ struct tap_f template constexpr T operator()(T&& x, const F& f) const { - return f(x), fit::forward(x); + return fit::apply(f, x), fit::forward(x); } }; diff --git a/fit/unpack.h b/fit/unpack.h index b362b21..2b92c59 100644 --- a/fit/unpack.h +++ b/fit/unpack.h @@ -31,7 +31,7 @@ /// /// F must be: /// -/// * [FunctionObject](concepts.md#functionobject) +/// * [Callable](concepts.md#callable) /// * MoveConstructible /// /// Example @@ -172,13 +172,13 @@ struct is_unpackable {}; template -struct unpack_adaptor : F +struct unpack_adaptor : detail::callable_base { typedef unpack_adaptor fit_rewritable1_tag; - FIT_INHERIT_CONSTRUCTOR(unpack_adaptor, F); + FIT_INHERIT_CONSTRUCTOR(unpack_adaptor, detail::callable_base); template - constexpr const F& base_function(Ts&&... xs) const + constexpr const detail::callable_base& base_function(Ts&&... xs) const { return always_ref(*this)(xs...); } @@ -223,7 +223,7 @@ struct unpack_adaptor : F }; struct failure - : failure_map + : failure_map> {}; FIT_RETURNS_CLASS(unpack_adaptor); @@ -233,7 +233,7 @@ struct unpack_adaptor : F constexpr auto operator()(T&& x) const FIT_RETURNS ( - detail::unpack_simple(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(x)), fit::forward(x)) + detail::unpack_simple(FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(x)), fit::forward(x)) ); template::value)>::type> constexpr auto operator()(T&& x, Ts&&... xs) const FIT_RETURNS ( - detail::unpack_join(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(x)), fit::forward(x), fit::forward(xs)...) + detail::unpack_join(FIT_MANGLE_CAST(const detail::callable_base&)(FIT_CONST_THIS->base_function(x)), fit::forward(x), fit::forward(xs)...) ); }; diff --git a/test/apply.cpp b/test/apply.cpp index 06a25f3..886fdf2 100644 --- a/test/apply.cpp +++ b/test/apply.cpp @@ -6,3 +6,57 @@ FIT_TEST_CASE() FIT_STATIC_TEST_CHECK(fit::apply(binary_class(), 1, 2) == 3); FIT_TEST_CHECK(fit::apply(binary_class(), 1, 2) == 3); } + +struct member_sum_f +{ + int i; + constexpr member_sum_f(int x) : i(x) + {} + + constexpr int add(int x) const + { + return i+x; + } +}; + +struct member_sum_f_derived +: member_sum_f +{ + constexpr member_sum_f_derived(int x) : member_sum_f(x) + {} +}; + +FIT_TEST_CASE() +{ + FIT_TEST_CHECK(fit::apply(&member_sum_f::add, member_sum_f(1), 2) == 3); + FIT_TEST_CHECK(fit::apply(&member_sum_f::add, member_sum_f_derived(1), 2) == 3); + +#ifdef __clang__ + FIT_STATIC_TEST_CHECK(fit::apply(&member_sum_f::add, member_sum_f(1), 2) == 3); + FIT_STATIC_TEST_CHECK(fit::apply(&member_sum_f::add, member_sum_f_derived(1), 2) == 3); +#endif + + static_assert(std::is_base_of::value, "Base of failed"); + std::unique_ptr msp(new member_sum_f(1)); + FIT_TEST_CHECK(fit::apply(&member_sum_f::add, msp, 2) == 3); + + std::unique_ptr mspd(new member_sum_f_derived(1)); + FIT_TEST_CHECK(fit::apply(&member_sum_f::add, mspd, 2) == 3); +} + +FIT_TEST_CASE() +{ + FIT_TEST_CHECK(fit::apply(&member_sum_f::i, member_sum_f(3)) == 3); + FIT_TEST_CHECK(fit::apply(&member_sum_f::i, member_sum_f_derived(3)) == 3); + +#ifdef __clang__ + FIT_STATIC_TEST_CHECK(fit::apply(&member_sum_f::i, member_sum_f(3)) == 3); + FIT_STATIC_TEST_CHECK(fit::apply(&member_sum_f::i, member_sum_f_derived(3)) == 3); +#endif + + std::unique_ptr msp(new member_sum_f(3)); + FIT_TEST_CHECK(fit::apply(&member_sum_f::i, msp) == 3); + + std::unique_ptr mspd(new member_sum_f_derived(3)); + FIT_TEST_CHECK(fit::apply(&member_sum_f::i, mspd) == 3); +} diff --git a/test/by.cpp b/test/by.cpp index 1436e20..16a0096 100644 --- a/test/by.cpp +++ b/test/by.cpp @@ -31,6 +31,17 @@ FIT_TEST_CASE() static_assert(fit::detail::is_default_constructible::value, "Not default constructible"); } +FIT_TEST_CASE() +{ +#ifndef _MSC_VER + constexpr +#endif + auto add = fit::_ + fit::_; + FIT_STATIC_TEST_CHECK(fit::by(select_x(), add)(foo(1), foo(2)) == 3); + FIT_TEST_CHECK(fit::by(&foo::x, add)(foo(1), foo(2)) == 3); + static_assert(fit::detail::is_default_constructible::value, "Not default constructible"); +} + FIT_TEST_CASE() { auto indirect_add = fit::by(*fit::_, fit::_ + fit::_); diff --git a/test/capture.cpp b/test/capture.cpp index 96d50c0..186e49c 100644 --- a/test/capture.cpp +++ b/test/capture.cpp @@ -25,4 +25,24 @@ FIT_TEST_CASE() FIT_STATIC_TEST_CHECK(fit::capture_decay(1)(binary_class())(2) == 3); FIT_TEST_CHECK(fit::capture_decay(1)(binary_class())(2) == 3); -} \ No newline at end of file +} + +struct add_member +{ + int i; + + add_member(int i) : i(i) + {} + + int add(int j) const + { + return i + j; + } +}; + +FIT_TEST_CASE() +{ + FIT_TEST_CHECK(fit::capture(add_member(1), 2)(&add_member::add)() == 3); + FIT_TEST_CHECK(fit::capture(add_member(1))(&add_member::add)(2) == 3); +} +