Initial Commit
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user