//---------------------------------------------------------------------------// // Copyright (c) 2013-2014 Kyle Lutz // // 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 #include #include #include namespace boost { namespace compute { namespace lambda { namespace detail { // function wrapper for get() in lambda expressions template struct get_func { template struct lambda_result { typedef typename proto::result_of::child_c::type Arg; typedef typename ::boost::compute::lambda::result_of::type T; typedef typename ::boost::compute::detail::get_result_type::type type; }; template 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() in lambda expressions // (e.g. ".x" for get<0>() with float4) template 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() specialization for std::pair template struct make_get_suffix > { static std::string value() { BOOST_STATIC_ASSERT(N < 2); if(N == 0){ return ".first"; } else { return ".second"; } }; }; // get() specialization for boost::tuple #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \ template \ struct make_get_suffix > \ { \ static std::string value() \ { \ BOOST_STATIC_ASSERT(N < n); \ return ".v" + boost::lexical_cast(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 static void dispatch_apply_terminal(Context &ctx, const Arg &arg) { typedef typename make_get_result_type::type T; proto::eval(arg, ctx); ctx.stream << make_get_suffix::value(); } template static void dispatch_apply_terminal(Context &ctx, placeholder) { ctx.stream << ::boost::compute::get()(::boost::get(ctx.args)); } template static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal) { dispatch_apply_terminal(ctx, proto::value(arg)); } template static void apply(Context &ctx, const Arg &arg) { dispatch_apply(ctx, arg, typename proto::tag_of::type()); } }; } // end detail namespace // get() template inline typename proto::result_of::make_expr< proto::tag::function, detail::get_func, const Arg& >::type const get(const Arg &arg) { return proto::make_expr( detail::get_func(), ::boost::ref(arg) ); } } // end lambda namespace } // end compute namespace } // end boost namespace #endif // BOOST_COMPUTE_LAMBDA_GET_HPP