| 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);/// \endcodetemplate<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...));}#elsetemplate<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
 |