summaryrefslogtreecommitdiff
path: root/boost/compute/functional/bind.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/compute/functional/bind.hpp')
-rw-r--r--boost/compute/functional/bind.hpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/boost/compute/functional/bind.hpp b/boost/compute/functional/bind.hpp
new file mode 100644
index 0000000000..0c5929f3b9
--- /dev/null
+++ b/boost/compute/functional/bind.hpp
@@ -0,0 +1,261 @@
+//---------------------------------------------------------------------------//
+// 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