1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
11 #ifndef BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
12 #define BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
14 #include <boost/mpl/int.hpp>
15 #include <boost/tuple/tuple.hpp>
16 #include <boost/type_traits/conditional.hpp>
18 #include <boost/compute/config.hpp>
19 #include <boost/compute/detail/meta_kernel.hpp>
23 namespace placeholders {
27 struct placeholder : boost::integral_constant<int, I>
32 placeholder<0> const _1;
33 placeholder<1> const _2;
35 } // end placeholders namespace
37 /// Meta-function returning \c true if \c T is a placeholder type.
39 struct is_placeholder : boost::false_type
45 struct is_placeholder<placeholders::placeholder<I> > : boost::true_type
51 template<class Function, class BoundArgs, class Args>
52 struct invoked_bound_function
54 invoked_bound_function(Function f, BoundArgs bound_args, Args args)
56 m_bound_args(bound_args),
61 // meta-function returning true if the N'th argument is a placeholder
63 struct is_placeholder_arg
65 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
67 typedef typename is_placeholder<nth_bound_arg>::type type;
68 static const bool value = is_placeholder<nth_bound_arg>::value;
78 struct get_arg_type<placeholders::placeholder<I> >
80 typedef typename boost::tuples::element<I, Args>::type type;
83 // meta-function returning the type of the N'th argument when invoked
85 struct get_nth_arg_type
87 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
89 typedef typename get_arg_type<nth_bound_arg>::type type;
93 typename get_nth_arg_type<N>::type get_nth_arg(
94 typename boost::enable_if_c<is_placeholder_arg<N>::value>::type* = 0
97 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
99 return boost::get<nth_bound_arg::value>(m_args);
103 typename get_nth_arg_type<N>::type get_nth_arg(
104 typename boost::disable_if_c<is_placeholder_arg<N>::value>::type* = 0
107 return boost::get<N>(m_bound_args);
111 BoundArgs m_bound_args;
115 template<class Function, class BoundArgs, class Args>
116 inline meta_kernel& apply_invoked_bound_function(
118 const invoked_bound_function<Function, BoundArgs, Args> &expr,
119 typename boost::enable_if_c<
120 boost::tuples::length<BoundArgs>::value == 1
124 return k << expr.m_function(expr.template get_nth_arg<0>());
127 template<class Function, class BoundArgs, class Args>
128 inline meta_kernel& apply_invoked_bound_function(
130 const invoked_bound_function<Function, BoundArgs, Args> &expr,
131 typename boost::enable_if_c<
132 boost::tuples::length<BoundArgs>::value == 2
136 return k << expr.m_function(expr.template get_nth_arg<0>(),
137 expr.template get_nth_arg<1>());
140 template<class Function, class BoundArgs, class Args>
141 inline meta_kernel& apply_invoked_bound_function(
143 const invoked_bound_function<Function, BoundArgs, Args> &expr,
144 typename boost::enable_if_c<
145 boost::tuples::length<BoundArgs>::value == 3
149 return k << expr.m_function(expr.template get_nth_arg<0>(),
150 expr.template get_nth_arg<1>(),
151 expr.template get_nth_arg<2>());
154 template<class Function, class BoundArgs, class Args>
155 inline meta_kernel& operator<<(
157 const invoked_bound_function<Function, BoundArgs, Args> &expr
160 return apply_invoked_bound_function(k, expr);
163 template<class Function, class BoundArgs>
164 struct bound_function
166 typedef int result_type;
168 bound_function(Function f, BoundArgs args)
175 detail::invoked_bound_function<
180 operator()(const Arg1 &arg1) const
182 return detail::invoked_bound_function<
186 >(m_function, m_args, boost::make_tuple(arg1));
189 template<class Arg1, class Arg2>
190 detail::invoked_bound_function<
193 boost::tuple<Arg1, Arg2>
195 operator()(const Arg1 &arg1, const Arg2 &arg2) const
197 return detail::invoked_bound_function<
200 boost::tuple<Arg1, Arg2>
201 >(m_function, m_args, boost::make_tuple(arg1, arg2));
208 } // end detail namespace
210 #if !defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
211 /// Returns a function wrapper which invokes \p f with \p args when called.
213 /// For example, to generate a unary function object which returns \c true
214 /// when its argument is less than \c 7:
216 /// using boost::compute::less;
217 /// using boost::compute::placeholders::_1;
219 /// auto less_than_seven = boost::compute::bind(less<int>(), _1, 7);
221 template<class F, class... Args>
222 inline detail::bound_function<F, boost::tuple<Args...> >
223 bind(F f, Args... args)
225 typedef typename boost::tuple<Args...> ArgsTuple;
227 return detail::bound_function<F, ArgsTuple>(f, boost::make_tuple(args...));
230 template<class F, class A1>
231 inline detail::bound_function<F, boost::tuple<A1> >
234 typedef typename boost::tuple<A1> Args;
236 return detail::bound_function<F, Args>(f, boost::make_tuple(a1));
239 template<class F, class A1, class A2>
240 inline detail::bound_function<F, boost::tuple<A1, A2> >
241 bind(F f, A1 a1, A2 a2)
243 typedef typename boost::tuple<A1, A2> Args;
245 return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2));
248 template<class F, class A1, class A2, class A3>
249 inline detail::bound_function<F, boost::tuple<A1, A2, A3> >
250 bind(F f, A1 a1, A2 a2, A3 a3)
252 typedef typename boost::tuple<A1, A2, A3> Args;
254 return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2, a3));
256 #endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
258 } // end compute namespace
259 } // end boost namespace
261 #endif // BOOST_COMPUTE_FUNCTIONAL_BIND_HPP