bind.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  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
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
  11. #define BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
  12. #include <boost/mpl/int.hpp>
  13. #include <boost/tuple/tuple.hpp>
  14. #include <boost/type_traits/conditional.hpp>
  15. #include <boost/compute/config.hpp>
  16. #include <boost/compute/detail/meta_kernel.hpp>
  17. namespace boost {
  18. namespace compute {
  19. namespace placeholders {
  20. /// \internal_
  21. template<int I>
  22. struct placeholder : boost::integral_constant<int, I>
  23. {
  24. placeholder() { }
  25. };
  26. placeholder<0> const _1;
  27. placeholder<1> const _2;
  28. } // end placeholders namespace
  29. /// Meta-function returning \c true if \c T is a placeholder type.
  30. template<class T>
  31. struct is_placeholder : boost::false_type
  32. {
  33. };
  34. /// \internal_
  35. template<int I>
  36. struct is_placeholder<placeholders::placeholder<I> > : boost::true_type
  37. {
  38. };
  39. namespace detail {
  40. template<class Function, class BoundArgs, class Args>
  41. struct invoked_bound_function
  42. {
  43. invoked_bound_function(Function f, BoundArgs bound_args, Args args)
  44. : m_function(f),
  45. m_bound_args(bound_args),
  46. m_args(args)
  47. {
  48. }
  49. // meta-function returning true if the N'th argument is a placeholder
  50. template<int N>
  51. struct is_placeholder_arg
  52. {
  53. typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
  54. typedef typename is_placeholder<nth_bound_arg>::type type;
  55. static const bool value = is_placeholder<nth_bound_arg>::value;
  56. };
  57. template<class Arg>
  58. struct get_arg_type
  59. {
  60. typedef Arg type;
  61. };
  62. template<int I>
  63. struct get_arg_type<placeholders::placeholder<I> >
  64. {
  65. typedef typename boost::tuples::element<I, Args>::type type;
  66. };
  67. // meta-function returning the type of the N'th argument when invoked
  68. template<int N>
  69. struct get_nth_arg_type
  70. {
  71. typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
  72. typedef typename get_arg_type<nth_bound_arg>::type type;
  73. };
  74. template<int N>
  75. typename get_nth_arg_type<N>::type get_nth_arg(
  76. typename boost::enable_if_c<is_placeholder_arg<N>::value>::type* = 0
  77. ) const
  78. {
  79. typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
  80. return boost::get<nth_bound_arg::value>(m_args);
  81. }
  82. template<int N>
  83. typename get_nth_arg_type<N>::type get_nth_arg(
  84. typename boost::disable_if_c<is_placeholder_arg<N>::value>::type* = 0
  85. ) const
  86. {
  87. return boost::get<N>(m_bound_args);
  88. }
  89. Function m_function;
  90. BoundArgs m_bound_args;
  91. Args m_args;
  92. };
  93. template<class Function, class BoundArgs, class Args>
  94. inline meta_kernel& apply_invoked_bound_function(
  95. meta_kernel &k,
  96. const invoked_bound_function<Function, BoundArgs, Args> &expr,
  97. typename boost::enable_if_c<
  98. boost::tuples::length<BoundArgs>::value == 1
  99. >::type* = 0
  100. )
  101. {
  102. return k << expr.m_function(expr.template get_nth_arg<0>());
  103. }
  104. template<class Function, class BoundArgs, class Args>
  105. inline meta_kernel& apply_invoked_bound_function(
  106. meta_kernel &k,
  107. const invoked_bound_function<Function, BoundArgs, Args> &expr,
  108. typename boost::enable_if_c<
  109. boost::tuples::length<BoundArgs>::value == 2
  110. >::type* = 0
  111. )
  112. {
  113. return k << expr.m_function(expr.template get_nth_arg<0>(),
  114. expr.template get_nth_arg<1>());
  115. }
  116. template<class Function, class BoundArgs, class Args>
  117. inline meta_kernel& apply_invoked_bound_function(
  118. meta_kernel &k,
  119. const invoked_bound_function<Function, BoundArgs, Args> &expr,
  120. typename boost::enable_if_c<
  121. boost::tuples::length<BoundArgs>::value == 3
  122. >::type* = 0
  123. )
  124. {
  125. return k << expr.m_function(expr.template get_nth_arg<0>(),
  126. expr.template get_nth_arg<1>(),
  127. expr.template get_nth_arg<2>());
  128. }
  129. template<class Function, class BoundArgs, class Args>
  130. inline meta_kernel& operator<<(
  131. meta_kernel &k,
  132. const invoked_bound_function<Function, BoundArgs, Args> &expr
  133. )
  134. {
  135. return apply_invoked_bound_function(k, expr);
  136. }
  137. template<class Function, class BoundArgs>
  138. struct bound_function
  139. {
  140. typedef int result_type;
  141. bound_function(Function f, BoundArgs args)
  142. : m_function(f),
  143. m_args(args)
  144. {
  145. }
  146. template<class Arg1>
  147. detail::invoked_bound_function<
  148. Function,
  149. BoundArgs,
  150. boost::tuple<Arg1>
  151. >
  152. operator()(const Arg1 &arg1) const
  153. {
  154. return detail::invoked_bound_function<
  155. Function,
  156. BoundArgs,
  157. boost::tuple<Arg1>
  158. >(m_function, m_args, boost::make_tuple(arg1));
  159. }
  160. template<class Arg1, class Arg2>
  161. detail::invoked_bound_function<
  162. Function,
  163. BoundArgs,
  164. boost::tuple<Arg1, Arg2>
  165. >
  166. operator()(const Arg1 &arg1, const Arg2 &arg2) const
  167. {
  168. return detail::invoked_bound_function<
  169. Function,
  170. BoundArgs,
  171. boost::tuple<Arg1, Arg2>
  172. >(m_function, m_args, boost::make_tuple(arg1, arg2));
  173. }
  174. Function m_function;
  175. BoundArgs m_args;
  176. };
  177. } // end detail namespace
  178. #if !defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
  179. /// Returns a function wrapper which invokes \p f with \p args when called.
  180. ///
  181. /// For example, to generate a unary function object which returns \c true
  182. /// when its argument is less than \c 7:
  183. /// \code
  184. /// using boost::compute::less;
  185. /// using boost::compute::placeholders::_1;
  186. ///
  187. /// auto less_than_seven = boost::compute::bind(less<int>(), _1, 7);
  188. /// \endcode
  189. template<class F, class... Args>
  190. inline detail::bound_function<F, boost::tuple<Args...> >
  191. bind(F f, Args... args)
  192. {
  193. typedef typename boost::tuple<Args...> ArgsTuple;
  194. return detail::bound_function<F, ArgsTuple>(f, boost::make_tuple(args...));
  195. }
  196. #else
  197. template<class F, class A1>
  198. inline detail::bound_function<F, boost::tuple<A1> >
  199. bind(F f, A1 a1)
  200. {
  201. typedef typename boost::tuple<A1> Args;
  202. return detail::bound_function<F, Args>(f, boost::make_tuple(a1));
  203. }
  204. template<class F, class A1, class A2>
  205. inline detail::bound_function<F, boost::tuple<A1, A2> >
  206. bind(F f, A1 a1, A2 a2)
  207. {
  208. typedef typename boost::tuple<A1, A2> Args;
  209. return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2));
  210. }
  211. template<class F, class A1, class A2, class A3>
  212. inline detail::bound_function<F, boost::tuple<A1, A2, A3> >
  213. bind(F f, A1 a1, A2 a2, A3 a3)
  214. {
  215. typedef typename boost::tuple<A1, A2, A3> Args;
  216. return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2, a3));
  217. }
  218. #endif // BOOST_COMPUTE_NO_VARIADIC_TEMPLATES
  219. } // end compute namespace
  220. } // end boost namespace
  221. #endif // BOOST_COMPUTE_FUNCTIONAL_BIND_HPP