-
Notifications
You must be signed in to change notification settings - Fork 333
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #200 from kylelutz/bind
Add bind() function
- Loading branch information
Showing
4 changed files
with
446 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
//---------------------------------------------------------------------------// | ||
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com> | ||
// | ||
// 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 | ||
// | ||
// See http://kylelutz.github.com/compute for more information. | ||
//---------------------------------------------------------------------------// | ||
|
||
#ifndef BOOST_COMPUTE_FUNCTIONAL_BIND_HPP | ||
#define BOOST_COMPUTE_FUNCTIONAL_BIND_HPP | ||
|
||
#include <boost/mpl/int.hpp> | ||
#include <boost/tuple/tuple.hpp> | ||
#include <boost/type_traits/conditional.hpp> | ||
|
||
#include <boost/compute/detail/meta_kernel.hpp> | ||
|
||
namespace boost { | ||
namespace compute { | ||
namespace placeholders { | ||
|
||
template<int I> | ||
struct placeholder : boost::integral_constant<int, I> | ||
{ | ||
placeholder() { } | ||
}; | ||
|
||
placeholder<0> const _1; | ||
placeholder<1> const _2; | ||
|
||
} // end placeholders namespace | ||
|
||
template<class T> | ||
struct is_placeholder : boost::false_type | ||
{ | ||
}; | ||
|
||
template<int I> | ||
struct is_placeholder<placeholders::placeholder<I> > : boost::true_type | ||
{ | ||
}; | ||
|
||
namespace detail { | ||
|
||
template<class Function, class BoundArgs, class Args> | ||
struct invoked_bound_function | ||
{ | ||
invoked_bound_function(Function f, BoundArgs bound_args, Args args) | ||
: m_function(f), | ||
m_bound_args(bound_args), | ||
m_args(args) | ||
{ | ||
} | ||
|
||
// meta-function returning true if the N'th argument is a placeholder | ||
template<int N> | ||
struct is_placeholder_arg | ||
{ | ||
typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg; | ||
|
||
typedef typename is_placeholder<nth_bound_arg>::type type; | ||
static const bool value = is_placeholder<nth_bound_arg>::value; | ||
}; | ||
|
||
template<class Arg> | ||
struct get_arg_type | ||
{ | ||
typedef Arg type; | ||
}; | ||
|
||
template<int I> | ||
struct get_arg_type<placeholders::placeholder<I> > | ||
{ | ||
typedef typename boost::tuples::element<I, Args>::type type; | ||
}; | ||
|
||
// meta-function returning the type of the N'th argument when invoked | ||
template<int N> | ||
struct get_nth_arg_type | ||
{ | ||
typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg; | ||
|
||
typedef typename get_arg_type<nth_bound_arg>::type type; | ||
}; | ||
|
||
template<int N> | ||
typename get_nth_arg_type<N>::type get_nth_arg( | ||
typename boost::enable_if_c<is_placeholder_arg<N>::value>::type* = 0 | ||
) const | ||
{ | ||
typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg; | ||
|
||
return boost::get<nth_bound_arg::value>(m_args); | ||
} | ||
|
||
template<int N> | ||
typename get_nth_arg_type<N>::type get_nth_arg( | ||
typename boost::disable_if_c<is_placeholder_arg<N>::value>::type* = 0 | ||
) const | ||
{ | ||
return boost::get<N>(m_bound_args); | ||
} | ||
|
||
Function m_function; | ||
BoundArgs m_bound_args; | ||
Args m_args; | ||
}; | ||
|
||
template<class Function, class BoundArgs, class Args> | ||
inline meta_kernel& apply_invoked_bound_function( | ||
meta_kernel &k, | ||
const invoked_bound_function<Function, BoundArgs, Args> &expr, | ||
typename boost::enable_if_c< | ||
boost::tuples::length<BoundArgs>::value == 1 | ||
>::type* = 0 | ||
) | ||
{ | ||
return k << expr.m_function(expr.template get_nth_arg<0>()); | ||
} | ||
|
||
template<class Function, class BoundArgs, class Args> | ||
inline meta_kernel& apply_invoked_bound_function( | ||
meta_kernel &k, | ||
const invoked_bound_function<Function, BoundArgs, Args> &expr, | ||
typename boost::enable_if_c< | ||
boost::tuples::length<BoundArgs>::value == 2 | ||
>::type* = 0 | ||
) | ||
{ | ||
return k << expr.m_function(expr.template get_nth_arg<0>(), | ||
expr.template get_nth_arg<1>()); | ||
} | ||
|
||
template<class Function, class BoundArgs, class Args> | ||
inline meta_kernel& apply_invoked_bound_function( | ||
meta_kernel &k, | ||
const invoked_bound_function<Function, BoundArgs, Args> &expr, | ||
typename boost::enable_if_c< | ||
boost::tuples::length<BoundArgs>::value == 3 | ||
>::type* = 0 | ||
) | ||
{ | ||
return k << expr.m_function(expr.template get_nth_arg<0>(), | ||
expr.template get_nth_arg<1>(), | ||
expr.template get_nth_arg<2>()); | ||
} | ||
|
||
template<class Function, class BoundArgs, class Args> | ||
inline meta_kernel& operator<<( | ||
meta_kernel &k, | ||
const invoked_bound_function<Function, BoundArgs, Args> &expr | ||
) | ||
{ | ||
return apply_invoked_bound_function(k, expr); | ||
} | ||
|
||
template<class Function, class BoundArgs> | ||
struct bound_function | ||
{ | ||
typedef int result_type; | ||
|
||
bound_function(Function f, BoundArgs args) | ||
: m_function(f), | ||
m_args(args) | ||
{ | ||
} | ||
|
||
template<class Arg1> | ||
detail::invoked_bound_function< | ||
Function, | ||
BoundArgs, | ||
boost::tuple<Arg1> | ||
> | ||
operator()(const Arg1 &arg1) const | ||
{ | ||
return detail::invoked_bound_function< | ||
Function, | ||
BoundArgs, | ||
boost::tuple<Arg1> | ||
>(m_function, m_args, boost::make_tuple(arg1)); | ||
} | ||
|
||
template<class Arg1, class Arg2> | ||
detail::invoked_bound_function< | ||
Function, | ||
BoundArgs, | ||
boost::tuple<Arg1, Arg2> | ||
> | ||
operator()(const Arg1 &arg1, const Arg2 &arg2) const | ||
{ | ||
return detail::invoked_bound_function< | ||
Function, | ||
BoundArgs, | ||
boost::tuple<Arg1, Arg2> | ||
>(m_function, m_args, boost::make_tuple(arg1, arg2)); | ||
} | ||
|
||
Function m_function; | ||
BoundArgs m_args; | ||
}; | ||
|
||
} // end detail namespace | ||
|
||
template<class F, class A1> | ||
inline detail::bound_function<F, boost::tuple<A1> > | ||
bind(F f, A1 a1) | ||
{ | ||
typedef typename boost::tuple<A1> Args; | ||
|
||
return detail::bound_function<F, Args>(f, boost::make_tuple(a1)); | ||
} | ||
|
||
template<class F, class A1, class A2> | ||
inline detail::bound_function<F, boost::tuple<A1, A2> > | ||
bind(F f, A1 a1, A2 a2) | ||
{ | ||
typedef typename boost::tuple<A1, A2> Args; | ||
|
||
return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2)); | ||
} | ||
|
||
template<class F, class A1, class A2, class A3> | ||
inline detail::bound_function<F, boost::tuple<A1, A2, A3> > | ||
bind(F f, A1 a1, A2 a2, A3 a3) | ||
{ | ||
typedef typename boost::tuple<A1, A2, A3> Args; | ||
|
||
return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2, a3)); | ||
} | ||
|
||
} // end compute namespace | ||
} // end boost namespace | ||
|
||
#endif // BOOST_COMPUTE_FUNCTIONAL_BIND_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.