File indexing completed on 2025-01-18 09:30:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
0012 #define BOOST_COMPUTE_FUNCTIONAL_BIND_HPP
0013
0014 #include <boost/mpl/int.hpp>
0015 #include <boost/tuple/tuple.hpp>
0016 #include <boost/type_traits/conditional.hpp>
0017
0018 #include <boost/compute/config.hpp>
0019 #include <boost/compute/detail/meta_kernel.hpp>
0020
0021 namespace boost {
0022 namespace compute {
0023 namespace placeholders {
0024
0025
0026 template<int I>
0027 struct placeholder : boost::integral_constant<int, I>
0028 {
0029 placeholder() { }
0030 };
0031
0032 placeholder<0> const _1;
0033 placeholder<1> const _2;
0034
0035 }
0036
0037
0038 template<class T>
0039 struct is_placeholder : boost::false_type
0040 {
0041 };
0042
0043
0044 template<int I>
0045 struct is_placeholder<placeholders::placeholder<I> > : boost::true_type
0046 {
0047 };
0048
0049 namespace detail {
0050
0051 template<class Function, class BoundArgs, class Args>
0052 struct invoked_bound_function
0053 {
0054 invoked_bound_function(Function f, BoundArgs bound_args, Args args)
0055 : m_function(f),
0056 m_bound_args(bound_args),
0057 m_args(args)
0058 {
0059 }
0060
0061
0062 template<int N>
0063 struct is_placeholder_arg
0064 {
0065 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
0066
0067 typedef typename is_placeholder<nth_bound_arg>::type type;
0068 static const bool value = is_placeholder<nth_bound_arg>::value;
0069 };
0070
0071 template<class Arg>
0072 struct get_arg_type
0073 {
0074 typedef Arg type;
0075 };
0076
0077 template<int I>
0078 struct get_arg_type<placeholders::placeholder<I> >
0079 {
0080 typedef typename boost::tuples::element<I, Args>::type type;
0081 };
0082
0083
0084 template<int N>
0085 struct get_nth_arg_type
0086 {
0087 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
0088
0089 typedef typename get_arg_type<nth_bound_arg>::type type;
0090 };
0091
0092 template<int N>
0093 typename get_nth_arg_type<N>::type get_nth_arg(
0094 typename boost::enable_if_c<is_placeholder_arg<N>::value>::type* = 0
0095 ) const
0096 {
0097 typedef typename boost::tuples::element<N, BoundArgs>::type nth_bound_arg;
0098
0099 return boost::get<nth_bound_arg::value>(m_args);
0100 }
0101
0102 template<int N>
0103 typename get_nth_arg_type<N>::type get_nth_arg(
0104 typename boost::disable_if_c<is_placeholder_arg<N>::value>::type* = 0
0105 ) const
0106 {
0107 return boost::get<N>(m_bound_args);
0108 }
0109
0110 Function m_function;
0111 BoundArgs m_bound_args;
0112 Args m_args;
0113 };
0114
0115 template<class Function, class BoundArgs, class Args>
0116 inline meta_kernel& apply_invoked_bound_function(
0117 meta_kernel &k,
0118 const invoked_bound_function<Function, BoundArgs, Args> &expr,
0119 typename boost::enable_if_c<
0120 boost::tuples::length<BoundArgs>::value == 1
0121 >::type* = 0
0122 )
0123 {
0124 return k << expr.m_function(expr.template get_nth_arg<0>());
0125 }
0126
0127 template<class Function, class BoundArgs, class Args>
0128 inline meta_kernel& apply_invoked_bound_function(
0129 meta_kernel &k,
0130 const invoked_bound_function<Function, BoundArgs, Args> &expr,
0131 typename boost::enable_if_c<
0132 boost::tuples::length<BoundArgs>::value == 2
0133 >::type* = 0
0134 )
0135 {
0136 return k << expr.m_function(expr.template get_nth_arg<0>(),
0137 expr.template get_nth_arg<1>());
0138 }
0139
0140 template<class Function, class BoundArgs, class Args>
0141 inline meta_kernel& apply_invoked_bound_function(
0142 meta_kernel &k,
0143 const invoked_bound_function<Function, BoundArgs, Args> &expr,
0144 typename boost::enable_if_c<
0145 boost::tuples::length<BoundArgs>::value == 3
0146 >::type* = 0
0147 )
0148 {
0149 return k << expr.m_function(expr.template get_nth_arg<0>(),
0150 expr.template get_nth_arg<1>(),
0151 expr.template get_nth_arg<2>());
0152 }
0153
0154 template<class Function, class BoundArgs, class Args>
0155 inline meta_kernel& operator<<(
0156 meta_kernel &k,
0157 const invoked_bound_function<Function, BoundArgs, Args> &expr
0158 )
0159 {
0160 return apply_invoked_bound_function(k, expr);
0161 }
0162
0163 template<class Function, class BoundArgs>
0164 struct bound_function
0165 {
0166 typedef int result_type;
0167
0168 bound_function(Function f, BoundArgs args)
0169 : m_function(f),
0170 m_args(args)
0171 {
0172 }
0173
0174 template<class Arg1>
0175 detail::invoked_bound_function<
0176 Function,
0177 BoundArgs,
0178 boost::tuple<Arg1>
0179 >
0180 operator()(const Arg1 &arg1) const
0181 {
0182 return detail::invoked_bound_function<
0183 Function,
0184 BoundArgs,
0185 boost::tuple<Arg1>
0186 >(m_function, m_args, boost::make_tuple(arg1));
0187 }
0188
0189 template<class Arg1, class Arg2>
0190 detail::invoked_bound_function<
0191 Function,
0192 BoundArgs,
0193 boost::tuple<Arg1, Arg2>
0194 >
0195 operator()(const Arg1 &arg1, const Arg2 &arg2) const
0196 {
0197 return detail::invoked_bound_function<
0198 Function,
0199 BoundArgs,
0200 boost::tuple<Arg1, Arg2>
0201 >(m_function, m_args, boost::make_tuple(arg1, arg2));
0202 }
0203
0204 Function m_function;
0205 BoundArgs m_args;
0206 };
0207
0208 }
0209
0210 #if !defined(BOOST_COMPUTE_NO_VARIADIC_TEMPLATES) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 template<class F, class... Args>
0222 inline detail::bound_function<F, boost::tuple<Args...> >
0223 bind(F f, Args... args)
0224 {
0225 typedef typename boost::tuple<Args...> ArgsTuple;
0226
0227 return detail::bound_function<F, ArgsTuple>(f, boost::make_tuple(args...));
0228 }
0229 #else
0230 template<class F, class A1>
0231 inline detail::bound_function<F, boost::tuple<A1> >
0232 bind(F f, A1 a1)
0233 {
0234 typedef typename boost::tuple<A1> Args;
0235
0236 return detail::bound_function<F, Args>(f, boost::make_tuple(a1));
0237 }
0238
0239 template<class F, class A1, class A2>
0240 inline detail::bound_function<F, boost::tuple<A1, A2> >
0241 bind(F f, A1 a1, A2 a2)
0242 {
0243 typedef typename boost::tuple<A1, A2> Args;
0244
0245 return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2));
0246 }
0247
0248 template<class F, class A1, class A2, class A3>
0249 inline detail::bound_function<F, boost::tuple<A1, A2, A3> >
0250 bind(F f, A1 a1, A2 a2, A3 a3)
0251 {
0252 typedef typename boost::tuple<A1, A2, A3> Args;
0253
0254 return detail::bound_function<F, Args>(f, boost::make_tuple(a1, a2, a3));
0255 }
0256 #endif
0257
0258 }
0259 }
0260
0261 #endif