diff options
Diffstat (limited to 'boost/compute/lambda/get.hpp')
-rw-r--r-- | boost/compute/lambda/get.hpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/boost/compute/lambda/get.hpp b/boost/compute/lambda/get.hpp new file mode 100644 index 0000000000..547c208e95 --- /dev/null +++ b/boost/compute/lambda/get.hpp @@ -0,0 +1,148 @@ +//---------------------------------------------------------------------------// +// 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_LAMBDA_GET_HPP +#define BOOST_COMPUTE_LAMBDA_GET_HPP + +#include <boost/preprocessor/repetition.hpp> + +#include <boost/compute/config.hpp> +#include <boost/compute/functional/get.hpp> +#include <boost/compute/lambda/placeholder.hpp> + +namespace boost { +namespace compute { +namespace lambda { +namespace detail { + +// function wrapper for get<N>() in lambda expressions +template<size_t N> +struct get_func +{ + template<class Expr, class Args> + struct lambda_result + { + typedef typename proto::result_of::child_c<Expr, 1>::type Arg; + typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type T; + typedef typename ::boost::compute::detail::get_result_type<N, T>::type type; + }; + + template<class Context, class Arg> + struct make_get_result_type + { + typedef typename boost::remove_cv< + typename boost::compute::lambda::result_of< + Arg, typename Context::args_tuple + >::type + >::type type; + }; + + // returns the suffix string for get<N>() in lambda expressions + // (e.g. ".x" for get<0>() with float4) + template<class T> + struct make_get_suffix + { + static std::string value() + { + BOOST_STATIC_ASSERT(N < 16); + + std::stringstream stream; + + if(N < 10){ + stream << ".s" << uint_(N); + } + else if(N < 16){ + stream << ".s" << char('a' + (N - 10)); + } + + return stream.str(); + } + }; + + // get<N>() specialization for std::pair<T1, T2> + template<class T1, class T2> + struct make_get_suffix<std::pair<T1, T2> > + { + static std::string value() + { + BOOST_STATIC_ASSERT(N < 2); + + if(N == 0){ + return ".first"; + } + else { + return ".second"; + } + }; + }; + + // get<N>() specialization for boost::tuple<T...> + #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \ + template<BOOST_PP_ENUM_PARAMS(n, class T)> \ + struct make_get_suffix<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \ + { \ + static std::string value() \ + { \ + BOOST_STATIC_ASSERT(N < n); \ + return ".v" + boost::lexical_cast<std::string>(N); \ + } \ + }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX, ~) + + #undef BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX + + template<class Context, class Arg> + static void dispatch_apply_terminal(Context &ctx, const Arg &arg) + { + typedef typename make_get_result_type<Context, Arg>::type T; + + proto::eval(arg, ctx); + ctx.stream << make_get_suffix<T>::value(); + } + + template<class Context, int I> + static void dispatch_apply_terminal(Context &ctx, placeholder<I>) + { + ctx.stream << ::boost::compute::get<N>()(::boost::get<I>(ctx.args)); + } + + template<class Context, class Arg> + static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal) + { + dispatch_apply_terminal(ctx, proto::value(arg)); + } + + template<class Context, class Arg> + static void apply(Context &ctx, const Arg &arg) + { + dispatch_apply(ctx, arg, typename proto::tag_of<Arg>::type()); + } +}; + +} // end detail namespace + +// get<N>() +template<size_t N, class Arg> +inline typename proto::result_of::make_expr< + proto::tag::function, detail::get_func<N>, const Arg& +>::type const +get(const Arg &arg) +{ + return proto::make_expr<proto::tag::function>( + detail::get_func<N>(), ::boost::ref(arg) + ); +} + +} // end lambda namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_LAMBDA_GET_HPP |