2
0
mirror of https://github.com/boostorg/hof.git synced 2026-01-31 20:22:11 +00:00

Merge pull request #85 from pfultz2/callable

Callable
This commit is contained in:
Paul Fultz II
2015-12-17 14:23:41 -06:00
34 changed files with 653 additions and 292 deletions

View File

@@ -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<Args>()...)` | 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<T, std::decay_t<decltype(x)>>()` is true, then `INVOKE(f, x, xs...)` is equivalent to `(x.*f)(xs...)`
- otherwise, if `std::decay_t<decltype(x)>` 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<T, std::decay_t<decltype(x)>>()` is true, then `INVOKE(f, x)` is equivalent to `x.*f`
- otherwise, if `std::decay_t<decltype(x)>` 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
------------

View File

@@ -32,7 +32,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
///
/// Example
/// -------
@@ -52,14 +52,117 @@
#include <fit/detail/forward.h>
#include <fit/detail/static_const_var.h>
namespace fit {
namespace detail {
#if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE
struct apply_mem_fn
{
template<class...>
struct convertible_args;
template<class T, class U>
struct is_convertible_args;
template<class... Ts, class... Us>
struct is_convertible_args<convertible_args<Ts...>, convertible_args<Us...>>
: and_<std::is_convertible<Ts, Us>...>
{};
#define FIT_APPLY_MEM_FN_CALL(cv) \
template <class R, class Base, class Derived, class... Ts, class... Us, class=typename std::enable_if<and_< \
std::is_base_of<Base, typename std::decay<Derived>::type>, \
is_convertible_args<convertible_args<Us...>, convertible_args<Ts...>> \
>::value>::type> \
constexpr R operator()(R (Base::*mf)(Ts...) cv, Derived&& ref, Us &&... xs) const \
{ \
return (fit::forward<Derived>(ref).*mf)(fit::forward<Us>(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 <class Base, class R, class Derived, class=typename std::enable_if<(
std::is_base_of<Base, typename std::decay<Derived>::type>::value
)>::type>
constexpr R operator()(R Base::*pmd, Derived&& ref) const
{
return fit::forward<Derived>(ref).*pmd;
}
};
template<class T, class U=decltype(*std::declval<T>())>
struct apply_deref
{ typedef U type; };
#endif
struct apply_f
{
#if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE
template<class F, class T, class... Ts, class=typename std::enable_if<(
std::is_member_function_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<T>, id_<Ts>...)
operator()(F&& f, T&& obj, Ts&&... xs) const FIT_SFINAE_MANUAL_RETURNS
(
apply_mem_fn()(f, fit::forward<T>(obj), fit::forward<Ts>(xs)...)
);
template<class F, class T, class... Ts, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
std::is_member_function_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_fn, id_<F>, id_<U>, id_<Ts>...)
operator()(F&& f, T&& obj, Ts&&... xs) const FIT_SFINAE_MANUAL_RETURNS
(
apply_mem_fn()(f, *fit::forward<T>(obj), fit::forward<Ts>(xs)...)
);
template<class F, class T, class=typename std::enable_if<(
std::is_member_object_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<T>)
operator()(F&& f, T&& obj) const FIT_SFINAE_MANUAL_RETURNS
(
apply_mem_data()(f, fit::forward<T>(obj))
);
template<class F, class T, class U=typename apply_deref<T>::type, class=typename std::enable_if<(
std::is_member_object_pointer<typename std::decay<F>::type>::value
)>::type>
constexpr FIT_SFINAE_MANUAL_RESULT(apply_mem_data, id_<F>, id_<U>)
operator()(F&& f, T&& obj) const FIT_SFINAE_MANUAL_RETURNS
(
apply_mem_data()(f, *fit::forward<T>(obj))
);
#else
template <class Base, class T, class Derived>
constexpr auto operator()(T Base::*pmd, Derived&& ref) const
FIT_RETURNS(fit::forward<Derived>(ref).*pmd);
template <class PMD, class Pointer>
constexpr auto operator()(PMD&& pmd, Pointer&& ptr) const
FIT_RETURNS((*fit::forward<Pointer>(ptr)).*fit::forward<PMD>(pmd));
template <class Base, class T, class Derived, class... Args>
constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const
FIT_RETURNS((fit::forward<Derived>(ref).*pmf)(fit::forward<Args>(args)...));
template <class PMF, class Pointer, class... Args>
constexpr auto operator()(PMF&& pmf, Pointer&& ptr, Args&&... args) const
FIT_RETURNS(((*fit::forward<Pointer>(ptr)).*fit::forward<PMF>(pmf))(fit::forward<Args>(args)...));
#endif
template<class F, class... Ts>
constexpr FIT_SFINAE_RESULT(F, id_<Ts>...) operator()(F&& f, Ts&&... xs) const FIT_SFINAE_RETURNS
constexpr FIT_SFINAE_RESULT(F, id_<Ts>...)
operator()(F&& f, Ts&&... xs) const FIT_SFINAE_RETURNS
(
f(fit::forward<Ts>(xs)...)
);

View File

@@ -34,7 +34,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
///
/// Ts must be:
///
@@ -57,6 +57,7 @@
#include <fit/returns.h>
#include <fit/detail/forward.h>
#include <fit/detail/static_const_var.h>
#include <fit/apply.h>
#include <fit/eval.h>
#ifndef FIT_NO_ORDERD_BRACE_INIT
@@ -95,7 +96,7 @@ struct eval_helper
R result;
template<class F, class... Ts>
constexpr eval_helper(const F& f, Ts&&... xs) : result(f(fit::forward<Ts>(xs)...))
constexpr eval_helper(const F& f, Ts&&... xs) : result(apply(f, fit::forward<Ts>(xs)...))
{}
constexpr R get_result()
@@ -109,7 +110,7 @@ struct eval_helper<void>
{
int x;
template<class F, class... Ts>
constexpr eval_helper(const F& f, Ts&&... xs) : x(f(fit::forward<Ts>(xs)...), 0)
constexpr eval_helper(const F& f, Ts&&... xs) : x(apply(f, fit::forward<Ts>(xs)...), 0)
{}
};
#endif
@@ -117,7 +118,7 @@ struct eval_helper<void>
struct apply_eval_f
{
template<class F, class... Ts, class R=decltype(
std::declval<const F&>()(fit::eval(std::declval<Ts>())...)
apply(std::declval<const F&>(), fit::eval(std::declval<Ts>())...)
),
class=typename std::enable_if<(!std::is_void<R>::value)>::type
>
@@ -134,7 +135,7 @@ struct apply_eval_f
}
template<class F, class... Ts, class R=decltype(
std::declval<const F&>()(fit::eval(std::declval<Ts>())...)
apply(std::declval<const F&>(), fit::eval(std::declval<Ts>())...)
),
class=typename std::enable_if<(std::is_void<R>::value)>::type
>

View File

@@ -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 <utility>
#include <fit/always.h>
#include <fit/detail/delegate.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/result_of.h>
#include <fit/detail/move.h>
#include <fit/detail/make.h>
@@ -160,17 +160,17 @@ template<class Projection, class F=void>
struct by_adaptor;
template<class Projection, class F>
struct by_adaptor : Projection, F
struct by_adaptor : detail::callable_base<Projection>, detail::callable_base<F>
{
typedef by_adaptor fit_rewritable_tag;
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
template<class... Ts>
constexpr const Projection& base_projection(Ts&&... xs) const
constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -182,51 +182,51 @@ struct by_adaptor : Projection, F
{
template<class... Ts>
struct of
: Failure::template of<decltype(std::declval<Projection>()(std::declval<Ts>()))...>
: Failure::template of<decltype(std::declval<detail::callable_base<Projection>>()(std::declval<Ts>()))...>
{};
};
};
struct failure
: failure_map<by_failure, F>
: failure_map<by_failure, detail::callable_base<F>>
{};
FIT_INHERIT_DEFAULT(by_adaptor, Projection, F)
FIT_INHERIT_DEFAULT(by_adaptor, detail::callable_base<Projection>, F)
template<class P, class G, FIT_ENABLE_IF_CONVERTIBLE(P, Projection), FIT_ENABLE_IF_CONVERTIBLE(G, F)>
template<class P, class G, FIT_ENABLE_IF_CONVERTIBLE(P, detail::callable_base<Projection>), FIT_ENABLE_IF_CONVERTIBLE(G, detail::callable_base<F>)>
constexpr by_adaptor(P&& p, G&& f)
: Projection(fit::forward<P>(p)), F(fit::forward<G>(f))
: detail::callable_base<Projection>(fit::forward<P>(p)), detail::callable_base<F>(fit::forward<G>(f))
{}
FIT_RETURNS_CLASS(by_adaptor);
template<class... Ts>
constexpr FIT_SFINAE_RESULT(const F&, result_of<const Projection&, id_<Ts>>...)
constexpr FIT_SFINAE_RESULT(const detail::callable_base<F>&, result_of<const detail::callable_base<Projection>&, id_<Ts>>...)
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<Projection>&)(FIT_CONST_THIS->base_projection(xs...)),
FIT_MANGLE_CAST(const detail::callable_base<F>&)(FIT_CONST_THIS->base_function(xs...)),
fit::forward<Ts>(xs)...
)
);
};
template<class Projection>
struct by_adaptor<Projection, void> : Projection
struct by_adaptor<Projection, void> : detail::callable_base<Projection>
{
typedef by_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr const Projection& base_projection(Ts&&... xs) const
constexpr const detail::callable_base<Projection>& base_projection(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
FIT_INHERIT_DEFAULT(by_adaptor, Projection)
FIT_INHERIT_DEFAULT(by_adaptor, detail::callable_base<Projection>)
template<class P, FIT_ENABLE_IF_CONVERTIBLE(P, Projection)>
template<class P, FIT_ENABLE_IF_CONVERTIBLE(P, detail::callable_base<Projection>)>
constexpr by_adaptor(P&& p)
: Projection(fit::forward<P>(p))
: detail::callable_base<Projection>(fit::forward<P>(p))
{}
FIT_RETURNS_CLASS(by_adaptor);

View File

@@ -8,7 +8,7 @@
#ifndef FIT_GUARD_CAPTURE_H
#define FIT_GUARD_CAPTURE_H
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/reveal.h>
#include <fit/pack.h>
#include <fit/always.h>
@@ -67,14 +67,14 @@ namespace fit {
namespace detail {
template<class F, class Pack>
struct capture_invoke : F, Pack
struct capture_invoke : detail::callable_base<F>, Pack
{
typedef capture_invoke fit_rewritable1_tag;
template<class X, class Y>
constexpr capture_invoke(X&& x, Y&& y) : F(fit::forward<X>(x)), Pack(fit::forward<Y>(y))
constexpr capture_invoke(X&& x, Y&& y) : detail::callable_base<F>(fit::forward<X>(x)), Pack(fit::forward<Y>(y))
{}
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -108,7 +108,7 @@ struct capture_invoke : F, Pack
};
struct failure
: failure_map<capture_failure, F>
: failure_map<capture_failure, detail::callable_base<F>>
{};
FIT_RETURNS_CLASS(capture_invoke);
@@ -120,7 +120,7 @@ struct capture_invoke : F, Pack
id_<const Pack&>,
result_of<decltype(fit::pack_forward), id_<Ts>...>
>::type,
id_<F&&>
id_<detail::callable_base<F>&&>
)
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<Ts>(xs)...)
)
(FIT_RETURNS_C_CAST(F&&)(FIT_CONST_THIS->base_function(xs...)))
(FIT_RETURNS_C_CAST(detail::callable_base<F>&&)(FIT_CONST_THIS->base_function(xs...)))
);
};

View File

@@ -34,7 +34,7 @@
///
/// F and Gs must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
/// Example
@@ -49,7 +49,7 @@
#include <fit/pack.h>
#include <fit/always.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/make.h>
namespace fit { namespace detail {
@@ -106,9 +106,9 @@ struct combine_adaptor_base<seq<Ns...>, F, Gs...>
template<class F, class... Gs>
struct combine_adaptor
: detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, F, Gs...>
: detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, detail::callable_base<F>, detail::callable_base<Gs>...>
{
typedef detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, F, Gs...> base_type;
typedef detail::combine_adaptor_base<typename detail::gens<sizeof...(Gs)>::type, detail::callable_base<F>, detail::callable_base<Gs>...> base_type;
FIT_INHERIT_CONSTRUCTOR(combine_adaptor, base_type)
};

View File

@@ -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 <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/always.h>
#include <fit/detail/delegate.h>
#include <fit/detail/compressed_pair.h>
@@ -97,30 +97,30 @@ struct compose_kernel : detail::compressed_pair<F1, F2>
}
template<class F, class... Fs>
struct compose_adaptor : detail::compose_kernel<F, FIT_JOIN(compose_adaptor, Fs...)>
struct compose_adaptor : detail::compose_kernel<detail::callable_base<F>, FIT_JOIN(compose_adaptor, detail::callable_base<Fs>...)>
{
typedef compose_adaptor fit_rewritable_tag;
typedef FIT_JOIN(compose_adaptor, Fs...) tail;
typedef detail::compose_kernel<F, tail> base_type;
typedef FIT_JOIN(compose_adaptor, detail::callable_base<Fs>...) tail;
typedef detail::compose_kernel<detail::callable_base<F>, tail> base_type;
FIT_INHERIT_DEFAULT(compose_adaptor, base_type)
template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, F), FIT_ENABLE_IF_CONSTRUCTIBLE(tail, Xs...)>
template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>), FIT_ENABLE_IF_CONSTRUCTIBLE(tail, Xs...)>
constexpr compose_adaptor(X&& f1, Xs&& ... fs)
: base_type(fit::forward<X>(f1), tail(fit::forward<Xs>(fs)...))
{}
};
template<class F>
struct compose_adaptor<F> : F
struct compose_adaptor<F> : detail::callable_base<F>
{
typedef compose_adaptor fit_rewritable_tag;
FIT_INHERIT_DEFAULT(compose_adaptor, F)
FIT_INHERIT_DEFAULT(compose_adaptor, detail::callable_base<F>)
template<class X, FIT_ENABLE_IF_CONVERTIBLE(X, F)>
template<class X, FIT_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>)>
constexpr compose_adaptor(X&& f1)
: F(fit::forward<X>(f1))
: detail::callable_base<F>(fit::forward<X>(f1))
{}
};

View File

@@ -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 <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/delegate.h>
#include <fit/detail/compressed_pair.h>
#include <fit/detail/move.h>
@@ -95,30 +95,30 @@ struct v_fold
template<class F, class State=void>
struct compress_adaptor
: detail::compressed_pair<F, State>
: detail::compressed_pair<detail::callable_base<F>, State>
{
typedef detail::compressed_pair<F, State> base_type;
typedef detail::compressed_pair<detail::callable_base<F>, State> base_type;
FIT_INHERIT_CONSTRUCTOR(compress_adaptor, base_type)
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return this->first(xs...);
}
template<class... Ts>
constexpr const State& get_state(Ts&&... xs) const
constexpr State get_state(Ts&&... xs) const
{
return this->second(xs...);
}
template<class... Ts>
constexpr FIT_SFINAE_RESULT(detail::v_fold, id_<const F&>, id_<const State&>, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(detail::v_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...)
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<F>&)(this->base_function(xs...)),
FIT_MANGLE_CAST(State)(this->get_state(xs...)),
fit::forward<Ts>(xs)...
)
)
@@ -127,22 +127,22 @@ struct compress_adaptor
template<class F>
struct compress_adaptor<F, void>
: F
: detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(compress_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(compress_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
template<class... Ts>
constexpr FIT_SFINAE_RESULT(detail::v_fold, id_<const F&>, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(detail::v_fold, id_<const detail::callable_base<F>&>, id_<Ts>...)
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<F>&)(this->base_function(xs...)),
fit::forward<Ts>(xs)...
)
)

View File

@@ -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 <fit/reveal.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/delegate.h>
#include <fit/detail/join.h>
#include <fit/detail/make.h>
@@ -106,14 +106,14 @@ struct conditional_adaptor_base<N, F, Fs...> : conditional_adaptor_base<N, F>, c
};
template<int N, class F>
struct conditional_adaptor_base<N, F> : F
struct conditional_adaptor_base<N, F> : detail::callable_base<F>
{
typedef F base;
typedef detail::callable_base<F> base;
FIT_INHERIT_CONSTRUCTOR(conditional_adaptor_base, F);
FIT_INHERIT_CONSTRUCTOR(conditional_adaptor_base, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -121,10 +121,10 @@ struct conditional_adaptor_base<N, F> : F
FIT_RETURNS_CLASS(conditional_adaptor_base);
template<class... Ts>
constexpr FIT_SFINAE_RESULT(const F&, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(const detail::callable_base<F>&, id_<Ts>...)
operator()(rank<N>, Ts&&... xs) const FIT_SFINAE_RETURNS
(
(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward<Ts>(xs)...)
(FIT_MANGLE_CAST(const detail::callable_base<F>&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward<Ts>(xs)...)
);
};

View File

@@ -32,7 +32,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
@@ -40,7 +40,7 @@
#include <fit/detail/delegate.h>
#include <fit/detail/move.h>
#include <fit/detail/make.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/static_const_var.h>
#include <fit/detail/compressed_pair.h>
@@ -125,22 +125,22 @@ struct decoration
}
template<class F>
constexpr decorator_invoke<F, T, D> operator()(F f) const
constexpr decorator_invoke<detail::callable_base<F>, T, D> operator()(F f) const
{
return decorator_invoke<F, T, D>(fit::move(f), this->get_data(f), this->get_decorator(f));
return decorator_invoke<detail::callable_base<F>, T, D>(fit::move(f), this->get_data(f), this->get_decorator(f));
}
};
}
template<class F>
struct decorate_adaptor : F
struct decorate_adaptor : detail::callable_base<F>
{
typedef decorate_adaptor fit_rewritable1_tag;
FIT_INHERIT_CONSTRUCTOR(decorate_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(decorate_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -148,9 +148,9 @@ struct decorate_adaptor : F
// TODO: Add predicate for constraints
template<class T>
constexpr detail::decoration<T, F> operator()(T x) const
constexpr detail::decoration<T, detail::callable_base<F>> operator()(T x) const
{
return detail::decoration<T, F>(fit::move(x), this->base_function(x));
return detail::decoration<T, detail::callable_base<F>>(fit::move(x), this->base_function(x));
}
};

View File

@@ -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 <fit/detail/delegate.h>
#include <fit/detail/result_of.h>
#include <fit/apply.h>
#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<class F>
struct non_class_function
{
F f;
FIT_DELGATE_CONSTRUCTOR(non_class_function, F, f)
template<class... Ts>
constexpr FIT_SFINAE_RESULT(apply_f, id_<F>, id_<Ts>...)
operator()(Ts&&... xs) const FIT_SFINAE_RETURNS
(
fit::apply(f, fit::forward<Ts>(xs)...)
);
};
#if FIT_HAS_TEMPLATE_ALIAS
template<class F>
using callable_base = typename std::conditional<(std::is_class<F>::value), F, non_class_function<F>>::type;
#else
template<class F>
struct callable_base_type
: std::conditional<(std::is_class<F>::value), F, non_class_function<F>>
{};
template<class F>
struct callable_base
: callable_base_type<F>::type
{
typedef typename callable_base_type<F>::type base;
FIT_INHERIT_CONSTRUCTOR(callable_base, base)
};
template<class F>
struct callable_base<callable_base<F>>
: callable_base<F>
{
typedef callable_base<F> base;
FIT_INHERIT_CONSTRUCTOR(callable_base, base)
};
#endif
}}
#endif

111
fit/detail/can_be_called.h Normal file
View File

@@ -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 <fit/detail/and.h>
#include <fit/detail/holder.h>
#include <fit/detail/sfinae.h>
namespace fit { namespace detail {
#if FIT_NO_EXPRESSION_SFINAE
struct dont_care
{
dont_care(...);
};
template<class T>
struct never_care
{
typedef dont_care type;
};
struct cant_be_called_type
{};
struct no_type
{};
template<class T, class U=typename std::remove_cv<typename std::remove_reference<T>::type>::type>
struct is_callable_wrapper_base
: std::conditional<std::is_class<U>::value, U, no_type>
{};
template<class F, class... Ts>
struct is_callable_wrapper : is_callable_wrapper_base<F>::type
{
is_callable_wrapper();
typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...);
operator pointer_to_function() const;
};
template<class T>
struct not_
: std::integral_constant<bool, !T::value>
{};
template<class F, class... Ts>
struct can_be_called
: not_<std::is_same<cant_be_called_type, typename std::decay<decltype(
is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...)
)>::type>>
{};
template<class F, class... Ts>
struct check_args;
template<class Res, class... Ts, class... Us>
struct check_args<Res(Us...), Ts...>
: and_<std::is_convertible<Ts, Us>...>
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(*)(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
#else
template<class... Ts>
struct callable_args
{};
template<class F, class Args, class=void>
struct can_be_called_impl
: std::false_type
{};
template<class F, class... Args>
struct can_be_called_impl<F, callable_args<Args...>, typename detail::holder<
decltype( std::declval<F>()(std::declval<Args>()...) )
>::type>
: std::true_type
{};
template<class F, class... Ts>
struct can_be_called
: can_be_called_impl<F, detail::callable_args<Ts...>>
{};
#endif
}}
#endif

View File

@@ -21,9 +21,9 @@
#if FIT_HAS_MANUAL_DEDUCTION || FIT_NO_EXPRESSION_SFINAE
#include <type_traits>
#include <fit/is_callable.h>
#include <fit/detail/and.h>
#include <fit/detail/holder.h>
#include <fit/detail/can_be_called.h>
namespace fit { namespace detail {
@@ -34,7 +34,7 @@ template<class F, class... Ts>
struct result_of_impl<
F,
holder<Ts...>,
typename std::enable_if<is_callable<F, typename Ts::type...>::value>::type
typename std::enable_if<can_be_called<F, typename Ts::type...>::value>::type
>
{
typedef decltype(std::declval<F>()(std::declval<typename Ts::type>()...)) type;

View File

@@ -37,7 +37,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
/// Example
@@ -48,7 +48,7 @@
///
#include <fit/always.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/reveal.h>
#include <fit/detail/delegate.h>
#include <fit/detail/move.h>
@@ -71,12 +71,12 @@ namespace fit {
namespace detail{
template<class Derived, class F>
struct fix_adaptor_base : F
struct fix_adaptor_base : detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(fix_adaptor_base, F);
FIT_INHERIT_CONSTRUCTOR(fix_adaptor_base, detail::callable_base<F>);
template<class... Ts>
FIT_FIX_CONSTEXPR const F& base_function(Ts&&... xs) const
FIT_FIX_CONSTEXPR const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -100,17 +100,17 @@ struct fix_adaptor_base : F
};
struct failure
: failure_map<fix_failure, F>
: failure_map<fix_failure, detail::callable_base<F>>
{};
FIT_RETURNS_CLASS(fix_adaptor_base);
template<class... Ts>
FIT_FIX_CONSTEXPR FIT_SFINAE_RESULT(const F&, id_<const Derived&>, id_<Ts>...)
FIT_FIX_CONSTEXPR FIT_SFINAE_RESULT(const detail::callable_base<F>&, id_<const Derived&>, id_<Ts>...)
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<F>&)(FIT_CONST_THIS->base_function(xs...))
(FIT_MANGLE_CAST(const Derived&)(FIT_CONST_THIS->derived_function(xs...)), fit::forward<Ts>(xs)...)
);
};

View File

@@ -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 <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/reveal.h>
#include <fit/detail/make.h>
#include <fit/detail/static_const_var.h>
@@ -50,10 +50,10 @@
namespace fit {
template<class F>
struct flip_adaptor : F
struct flip_adaptor : detail::callable_base<F>
{
typedef flip_adaptor fit_rewritable1_tag;
FIT_INHERIT_CONSTRUCTOR(flip_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(flip_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
@@ -74,16 +74,16 @@ struct flip_adaptor : F
};
struct failure
: failure_map<flip_failure, F>
: failure_map<flip_failure, detail::callable_base<F>>
{};
FIT_RETURNS_CLASS(flip_adaptor);
template<class T, class U, class... Ts>
constexpr FIT_SFINAE_RESULT(const F&, id_<U>, id_<T>, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(const detail::callable_base<F>&, id_<U>, id_<T>, id_<Ts>...)
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<F>&)(FIT_CONST_THIS->base_function(xs...)))
(fit::forward<U>(y), fit::forward<T>(x), fit::forward<Ts>(xs)...)
);
};

View File

@@ -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 <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/always.h>
#include <fit/detail/delegate.h>
#include <fit/detail/compressed_pair.h>
@@ -77,20 +77,20 @@
namespace fit { namespace detail {
template<class F1, class F2>
struct flow_kernel : detail::compressed_pair<F1, F2>
struct flow_kernel : detail::compressed_pair<detail::callable_base<F1>, detail::callable_base<F2>>
{
typedef detail::compressed_pair<F1, F2> base_type;
typedef detail::compressed_pair<detail::callable_base<F1>, detail::callable_base<F2>> base_type;
FIT_INHERIT_CONSTRUCTOR(flow_kernel, base_type)
FIT_RETURNS_CLASS(flow_kernel);
template<class... Ts>
constexpr FIT_SFINAE_RESULT(const F2&, result_of<const F1&, id_<Ts>...>)
constexpr FIT_SFINAE_RESULT(const detail::callable_base<F2>&, result_of<const detail::callable_base<F1>&, id_<Ts>...>)
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<Ts>(xs)...)
FIT_MANGLE_CAST(const detail::callable_base<F2>&)(FIT_CONST_THIS->second(xs...))(
FIT_MANGLE_CAST(const detail::callable_base<F1>&)(FIT_CONST_THIS->first(xs...))(fit::forward<Ts>(xs)...)
)
);
};
@@ -112,14 +112,14 @@ struct flow_adaptor : detail::flow_kernel<F, FIT_JOIN(flow_adaptor, Fs...)>
};
template<class F>
struct flow_adaptor<F> : F
struct flow_adaptor<F> : detail::callable_base<F>
{
typedef flow_adaptor fit_rewritable_tag;
FIT_INHERIT_DEFAULT(flow_adaptor, F)
FIT_INHERIT_DEFAULT(flow_adaptor, detail::callable_base<F>)
template<class X, FIT_ENABLE_IF_CONVERTIBLE(X, F)>
template<class X, FIT_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>)>
constexpr flow_adaptor(X&& f1)
: F(fit::forward<X>(f1))
: detail::callable_base<F>(fit::forward<X>(f1))
{}
};

View File

@@ -36,7 +36,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
/// Example
@@ -58,7 +58,7 @@
///
#include <fit/always.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/forward.h>
#include <fit/detail/delegate.h>
#include <fit/detail/move.h>
@@ -74,9 +74,9 @@ struct if_depend
{};
template<bool Cond, class F>
struct if_adaptor : F
struct if_adaptor : detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(if_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(if_adaptor, detail::callable_base<F>)
};
template<class F>

View File

@@ -61,7 +61,7 @@
#include <fit/detail/static_const_var.h>
namespace fit {
// TODO: Support non-classes as well
template<class F>
struct indirect_adaptor : F
{

View File

@@ -34,7 +34,7 @@
///
/// F must be:
///
/// * [BinaryFunctionObject](concepts.md#binaryfunctionobject)
/// * [BinaryCallable](concepts.md#binarycallable)
/// * MoveConstructible
///
/// Example
@@ -55,7 +55,7 @@
///
#include <fit/detail/delegate.h>
#include <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/always.h>
#include <fit/detail/move.h>
#include <fit/detail/make.h>
@@ -105,19 +105,19 @@ constexpr postfix_adaptor<T, F> make_postfix_adaptor(T&& x, F f)
}
template<class F>
struct infix_adaptor : F
struct infix_adaptor : detail::callable_base<F>
{
typedef infix_adaptor fit_rewritable1_tag;
FIT_INHERIT_CONSTRUCTOR(infix_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(infix_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
template<class... Ts>
constexpr const F& infix_base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& infix_base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -127,7 +127,7 @@ struct infix_adaptor : F
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const FIT_RETURNS
(
(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward<Ts>(xs)...)
(FIT_MANGLE_CAST(const detail::callable_base<F>&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward<Ts>(xs)...)
);
};

View File

@@ -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<is_callable_class, int>(), "Not callable");
///
#include <utility>
#include <type_traits>
#include <fit/detail/holder.h>
#include <fit/detail/and.h>
#include <fit/detail/sfinae.h>
#include <fit/detail/can_be_called.h>
#include <fit/apply.h>
namespace fit {
#if FIT_NO_EXPRESSION_SFINAE
namespace detail {
struct dont_care
{
dont_care(...);
};
template<class T>
struct never_care
{
typedef dont_care type;
};
struct cant_be_called_type
{};
template<class F, class... Ts>
struct is_callable_wrapper : std::remove_cv<typename std::remove_reference<F>::type>::type
{
is_callable_wrapper();
typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...);
operator pointer_to_function() const;
};
template<class T>
struct not_
: std::integral_constant<bool, !T::value>
{};
template<class F, class... Ts>
struct can_be_called
: not_<std::is_same<cant_be_called_type, typename std::decay<decltype(
is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...)
)>::type>>
{};
template<class F, class... Ts>
struct check_args;
template<class Res, class... Ts, class... Us>
struct check_args<Res(Us...), Ts...>
: and_<std::is_convertible<Ts, Us>...>
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(*)(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
template<class Res, class... Ts, class... Us>
struct can_be_called<Res(Us...), Ts...>
: std::conditional<sizeof...(Ts) == sizeof...(Us),
check_args<Res(Us...), Ts...>,
std::false_type
>::type
{};
}
template<class F, class... Ts>
struct is_callable
: detail::can_be_called<F, Ts...>
: detail::can_be_called<detail::apply_f, F, Ts...>
{};
#else
namespace detail {
template<class... Ts>
struct callable_args
{};
template<class F, class Args, class=void>
struct is_callable_impl
: std::false_type
{};
template<class F, class... Args>
struct is_callable_impl<F, callable_args<Args...>, typename detail::holder<
decltype( std::declval<F>()(std::declval<Args>()...) )
>::type>
: std::true_type
{};
}
template<class F, class... Ts>
struct is_callable
: detail::is_callable_impl<F, detail::callable_args<Ts...>>
{};
#endif
}
#endif

View File

@@ -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<F> make_lazy_nullary_invoker(F f)
template<class F>
struct lazy_adaptor : F
struct lazy_adaptor : detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(lazy_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(lazy_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -240,7 +240,7 @@ struct lazy_adaptor : F
template<class T, class... Ts>
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<F>&&)(FIT_CONST_THIS->base_function(x, xs...)),
pack(fit::move(x), fit::move(xs)...))
);
@@ -248,7 +248,7 @@ struct lazy_adaptor : F
template<class Unused=int>
constexpr detail::lazy_nullary_invoker<F> operator()() const
{
return fit::detail::make_lazy_nullary_invoker((F&&)(
return fit::detail::make_lazy_nullary_invoker((detail::callable_base<F>&&)(
this->base_function(Unused())
));
}

View File

@@ -30,7 +30,7 @@
///
/// Fs must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
/// Example
@@ -62,6 +62,7 @@
///
#include <fit/reveal.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/delegate.h>
#include <fit/detail/move.h>
#include <fit/detail/make.h>
@@ -72,20 +73,20 @@ namespace fit {
template<class...Fs> struct match_adaptor;
template<class F, class...Fs>
struct match_adaptor<F, Fs...> : F, match_adaptor<Fs...>
struct match_adaptor<F, Fs...> : detail::callable_base<F>, match_adaptor<Fs...>
{
typedef match_adaptor<Fs...> base;
typedef match_adaptor fit_rewritable_tag;
struct failure
: failure_for<F, Fs...>
: failure_for<detail::callable_base<F>, Fs...>
{};
FIT_INHERIT_DEFAULT(match_adaptor, F, base);
FIT_INHERIT_DEFAULT(match_adaptor, detail::callable_base<F>, base);
template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, F), FIT_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)>
template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, detail::callable_base<F>), FIT_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)>
constexpr match_adaptor(X&& f1, Xs&& ... fs)
: F(fit::forward<X>(f1)), base(fit::forward<Xs>(fs)...)
: detail::callable_base<F>(fit::forward<X>(f1)), base(fit::forward<Xs>(fs)...)
{}
using F::operator();
@@ -93,13 +94,13 @@ struct match_adaptor<F, Fs...> : F, match_adaptor<Fs...>
};
template<class F>
struct match_adaptor<F> : F
struct match_adaptor<F> : detail::callable_base<F>
{
typedef F base;
typedef detail::callable_base<F> base;
typedef match_adaptor fit_rewritable_tag;
using F::operator();
FIT_INHERIT_CONSTRUCTOR(match_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(match_adaptor, detail::callable_base<F>);
};
FIT_DECLARE_STATIC_VAR(match, detail::make<match_adaptor>);

View File

@@ -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<class F>
struct partial_adaptor_base<F, void>
template<class Derived, class F>
struct partial_adaptor_pack_base
{
typedef conditional_adaptor
<
F,
partial_adaptor_pack<partial_adaptor<F, void>, F>
partial_adaptor_pack<Derived, F>
> type;
};
@@ -214,14 +214,14 @@ struct partial_adaptor : detail::partial_adaptor_base<F, Pack>::type, F, Pack
};
template<class F>
struct partial_adaptor<F, void> : detail::partial_adaptor_base<F, void>::type
struct partial_adaptor<F, void> : detail::partial_adaptor_pack_base<partial_adaptor<F, void>, detail::callable_base<F>>::type
{
typedef typename detail::partial_adaptor_base<F, void>::type base;
typedef typename detail::partial_adaptor_pack_base<partial_adaptor<F, void>, detail::callable_base<F>>::type base;
typedef partial_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr const F& base_function(Ts&&...) const
constexpr const detail::callable_base<F>& base_function(Ts&&...) const
{
return *this;
}
@@ -231,6 +231,7 @@ struct partial_adaptor<F, void> : detail::partial_adaptor_base<F, void>::type
FIT_INHERIT_CONSTRUCTOR(partial_adaptor, base);
};
// Make partial_adaptor work with pipable_adaptor by removing its pipableness
template<class F>
struct partial_adaptor<pipable_adaptor<F>, void>

View File

@@ -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<F, Pack>& p) FIT_RETURNS
template<class F>
struct pipable_adaptor
: conditional_adaptor<F, detail::pipe_pack<pipable_adaptor<F>, F> >
: conditional_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> >
{
typedef conditional_adaptor<F, detail::pipe_pack<pipable_adaptor<F>, F> > base;
typedef conditional_adaptor<detail::callable_base<F>, detail::pipe_pack<pipable_adaptor<F>, detail::callable_base<F>> > base;
typedef pipable_adaptor fit_rewritable_tag;
FIT_INHERIT_CONSTRUCTOR(pipable_adaptor, base);
constexpr const F& base_function() const
constexpr const detail::callable_base<F>& base_function() const
{
return *this;
}

View File

@@ -31,7 +31,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
@@ -44,11 +44,11 @@
namespace fit {
template<class F>
struct protect_adaptor : F
struct protect_adaptor : detail::callable_base<F>
{
typedef protect_adaptor fit_rewritable1_tag;
template<class... Ts>
constexpr protect_adaptor(Ts&&... xs) : F(fit::forward<Ts>(xs)...)
constexpr protect_adaptor(Ts&&... xs) : detail::callable_base<F>(fit::forward<Ts>(xs)...)
{}
};

View File

@@ -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<decltype(int_result(true)), int>::value, "Not the same type");
///
#include <fit/detail/delegate.h>
#include <fit/detail/callable_base.h>
#include <fit/is_callable.h>
#include <fit/always.h>
#include <fit/reveal.h>
@@ -58,18 +58,18 @@
namespace fit {
template<class Result, class F>
struct result_adaptor : F
struct result_adaptor : detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(result_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
typedef Result result_type;
struct failure
: failure_for<F>
: failure_for<detail::callable_base<F>>
{};
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -82,14 +82,14 @@ struct result_adaptor : F
};
template<class F>
struct result_adaptor<void, F> : F
struct result_adaptor<void, F> : detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(result_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
typedef void result_type;
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}

View File

@@ -32,7 +32,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
@@ -41,6 +41,7 @@
#include <fit/is_callable.h>
#include <fit/identity.h>
#include <fit/detail/move.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/delegate.h>
#include <fit/detail/holder.h>
#include <fit/detail/join.h>
@@ -211,13 +212,13 @@ struct failure_for
template<class F>
struct reveal_adaptor
: detail::traverse_failure<F>, F
: detail::traverse_failure<detail::callable_base<F>>, detail::callable_base<F>
{
typedef reveal_adaptor fit_rewritable1_tag;
using detail::traverse_failure<F>::operator();
using F::operator();
using detail::traverse_failure<detail::callable_base<F>>::operator();
using detail::callable_base<F>::operator();
FIT_INHERIT_CONSTRUCTOR(reveal_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(reveal_adaptor, detail::callable_base<F>);
};
// Avoid double reveals, it causes problem on gcc 4.6
template<class F>

View File

@@ -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 <fit/detail/result_of.h>
#include <fit/detail/callable_base.h>
#include <fit/detail/delegate.h>
#include <fit/detail/compressed_pair.h>
#include <fit/detail/move.h>
@@ -96,30 +96,30 @@ struct v_reverse_fold
template<class F, class State=void>
struct reverse_compress_adaptor
: detail::compressed_pair<F, State>
: detail::compressed_pair<detail::callable_base<F>, State>
{
typedef detail::compressed_pair<F, State> base_type;
typedef detail::compressed_pair<detail::callable_base<F>, State> base_type;
FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, base_type)
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return this->first(xs...);
}
template<class... Ts>
constexpr const State& get_state(Ts&&... xs) const
constexpr State get_state(Ts&&... xs) const
{
return this->second(xs...);
}
template<class... Ts>
constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_<const F&>, id_<const State&>, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<State>, id_<Ts>...)
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<F>&)(this->base_function(xs...)),
FIT_MANGLE_CAST(State)(this->get_state(xs...)),
fit::forward<Ts>(xs)...
)
)
@@ -128,22 +128,22 @@ struct reverse_compress_adaptor
template<class F>
struct reverse_compress_adaptor<F, void>
: F
: detail::callable_base<F>
{
FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, F)
FIT_INHERIT_CONSTRUCTOR(reverse_compress_adaptor, detail::callable_base<F>)
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
template<class... Ts>
constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_<const F&>, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(detail::v_reverse_fold, id_<const detail::callable_base<F>&>, id_<Ts>...)
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<F>&)(this->base_function(xs...)),
fit::forward<Ts>(xs)...
)
)

View File

@@ -33,7 +33,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [Callable](concepts.md#callable)
/// * MoveConstructible
///
/// Example
@@ -51,13 +51,13 @@
namespace fit {
template<class F>
struct rotate_adaptor : F
struct rotate_adaptor : detail::callable_base<F>
{
typedef rotate_adaptor fit_rewritable1_tag;
FIT_INHERIT_CONSTRUCTOR(rotate_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(rotate_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -75,16 +75,16 @@ struct rotate_adaptor : F
};
struct failure
: failure_map<rotate_failure, F>
: failure_map<rotate_failure, detail::callable_base<F>>
{};
FIT_RETURNS_CLASS(rotate_adaptor);
template<class T, class... Ts>
constexpr FIT_SFINAE_RESULT(const F&, id_<Ts>..., id_<T>)
constexpr FIT_SFINAE_RESULT(const detail::callable_base<F>&, id_<Ts>..., id_<T>)
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<F>&)(FIT_CONST_THIS->base_function(xs...)))
(fit::forward<Ts>(xs)..., fit::forward<T>(x))
);
};

View File

@@ -30,7 +30,7 @@
///
/// F must be:
///
/// * [FunctionObject](concepts.md#functionobject)
/// * [UnaryCallable](concepts.md#unarycallable)
///
/// Example
/// -------
@@ -51,6 +51,7 @@
///
#include <fit/pipable.h>
#include <fit/apply.h>
#include <fit/detail/static_const_var.h>
namespace fit { namespace detail {
@@ -60,7 +61,7 @@ struct tap_f
template<class T, class F>
constexpr T operator()(T&& x, const F& f) const
{
return f(x), fit::forward<T>(x);
return fit::apply(f, x), fit::forward<T>(x);
}
};

View File

@@ -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<class F>
struct unpack_adaptor : F
struct unpack_adaptor : detail::callable_base<F>
{
typedef unpack_adaptor fit_rewritable1_tag;
FIT_INHERIT_CONSTRUCTOR(unpack_adaptor, F);
FIT_INHERIT_CONSTRUCTOR(unpack_adaptor, detail::callable_base<F>);
template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}
@@ -223,7 +223,7 @@ struct unpack_adaptor : F
};
struct failure
: failure_map<unpack_failure, F>
: failure_map<unpack_failure, detail::callable_base<F>>
{};
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<T>(x))
detail::unpack_simple(FIT_MANGLE_CAST(const detail::callable_base<F>&)(FIT_CONST_THIS->base_function(x)), fit::forward<T>(x))
);
template<class T, class... Ts, class=typename std::enable_if<(detail::and_<
@@ -241,7 +241,7 @@ struct unpack_adaptor : F
>::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<T>(x), fit::forward<Ts>(xs)...)
detail::unpack_join(FIT_MANGLE_CAST(const detail::callable_base<F>&)(FIT_CONST_THIS->base_function(x)), fit::forward<T>(x), fit::forward<Ts>(xs)...)
);
};

View File

@@ -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<member_sum_f, member_sum_f>::value, "Base of failed");
std::unique_ptr<member_sum_f> msp(new member_sum_f(1));
FIT_TEST_CHECK(fit::apply(&member_sum_f::add, msp, 2) == 3);
std::unique_ptr<member_sum_f_derived> 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<member_sum_f> msp(new member_sum_f(3));
FIT_TEST_CHECK(fit::apply(&member_sum_f::i, msp) == 3);
std::unique_ptr<member_sum_f_derived> mspd(new member_sum_f_derived(3));
FIT_TEST_CHECK(fit::apply(&member_sum_f::i, mspd) == 3);
}

View File

@@ -31,6 +31,17 @@ FIT_TEST_CASE()
static_assert(fit::detail::is_default_constructible<decltype(fit::by(select_x(), add))>::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<decltype(fit::by(select_x(), add))>::value, "Not default constructible");
}
FIT_TEST_CASE()
{
auto indirect_add = fit::by(*fit::_, fit::_ + fit::_);

View File

@@ -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);
}
}
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);
}