123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- //---------------------------------------------------------------------------//
- // 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://boostorg.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/config.hpp>
- #include <boost/compute/detail/meta_kernel.hpp>
- namespace boost {
- namespace compute {
- namespace placeholders {
- /// \internal_
- template<int I>
- struct placeholder : boost::integral_constant<int, I>
- {
- placeholder() { }
- };
- placeholder<0> const _1;
- placeholder<1> const _2;
- } // end placeholders namespace
- /// Meta-function returning \c true if \c T is a placeholder type.
- template<class T>
- struct is_placeholder : boost::false_type
- {
- };
- /// \internal_
- 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
- #if !defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
- /// Returns a function wrapper which invokes \p f with \p args when called.
- ///
- /// For example, to generate a unary function object which returns \c true
- /// when its argument is less than \c 7:
- /// \code
- /// using boost::compute::less;
- /// using boost::compute::placeholders::_1;
- ///
- /// auto less_than_seven = boost::compute::bind(less<int>(), _1, 7);
- /// \endcode
- template<class F, class... Args>
- inline detail::bound_function<F, boost::tuple<Args...> >
- bind(F f, Args... args)
- {
- typedef typename boost::tuple<Args...> ArgsTuple;
- return detail::bound_function<F, ArgsTuple>(f, boost::make_tuple(args...));
- }
- #else
- 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));
- }
- #endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
- } // end compute namespace
- } // end boost namespace
- #endif // BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
|