get.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_LAMBDA_GET_HPP
  11. #define BOOST_COMPUTE_LAMBDA_GET_HPP
  12. #include <boost/preprocessor/repetition.hpp>
  13. #include <boost/compute/config.hpp>
  14. #include <boost/compute/functional/get.hpp>
  15. #include <boost/compute/lambda/placeholder.hpp>
  16. namespace boost {
  17. namespace compute {
  18. namespace lambda {
  19. namespace detail {
  20. // function wrapper for get<N>() in lambda expressions
  21. template<size_t N>
  22. struct get_func
  23. {
  24. template<class Expr, class Args>
  25. struct lambda_result
  26. {
  27. typedef typename proto::result_of::child_c<Expr, 1>::type Arg;
  28. typedef typename ::boost::compute::lambda::result_of<Arg, Args>::type T;
  29. typedef typename ::boost::compute::detail::get_result_type<N, T>::type type;
  30. };
  31. template<class Context, class Arg>
  32. struct make_get_result_type
  33. {
  34. typedef typename boost::remove_cv<
  35. typename boost::compute::lambda::result_of<
  36. Arg, typename Context::args_tuple
  37. >::type
  38. >::type type;
  39. };
  40. // returns the suffix string for get<N>() in lambda expressions
  41. // (e.g. ".x" for get<0>() with float4)
  42. template<class T>
  43. struct make_get_suffix
  44. {
  45. static std::string value()
  46. {
  47. BOOST_STATIC_ASSERT(N < 16);
  48. std::stringstream stream;
  49. if(N < 10){
  50. stream << ".s" << uint_(N);
  51. }
  52. else if(N < 16){
  53. stream << ".s" << char('a' + (N - 10));
  54. }
  55. return stream.str();
  56. }
  57. };
  58. // get<N>() specialization for std::pair<T1, T2>
  59. template<class T1, class T2>
  60. struct make_get_suffix<std::pair<T1, T2> >
  61. {
  62. static std::string value()
  63. {
  64. BOOST_STATIC_ASSERT(N < 2);
  65. if(N == 0){
  66. return ".first";
  67. }
  68. else {
  69. return ".second";
  70. }
  71. };
  72. };
  73. // get<N>() specialization for boost::tuple<T...>
  74. #define BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX(z, n, unused) \
  75. template<BOOST_PP_ENUM_PARAMS(n, class T)> \
  76. struct make_get_suffix<boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> > \
  77. { \
  78. static std::string value() \
  79. { \
  80. BOOST_STATIC_ASSERT(N < n); \
  81. return ".v" + boost::lexical_cast<std::string>(N); \
  82. } \
  83. };
  84. BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX, ~)
  85. #undef BOOST_COMPUTE_LAMBDA_GET_MAKE_TUPLE_SUFFIX
  86. template<class Context, class Arg>
  87. static void dispatch_apply_terminal(Context &ctx, const Arg &arg)
  88. {
  89. typedef typename make_get_result_type<Context, Arg>::type T;
  90. proto::eval(arg, ctx);
  91. ctx.stream << make_get_suffix<T>::value();
  92. }
  93. template<class Context, int I>
  94. static void dispatch_apply_terminal(Context &ctx, placeholder<I>)
  95. {
  96. ctx.stream << ::boost::compute::get<N>()(::boost::get<I>(ctx.args));
  97. }
  98. template<class Context, class Arg>
  99. static void dispatch_apply(Context &ctx, const Arg &arg, proto::tag::terminal)
  100. {
  101. dispatch_apply_terminal(ctx, proto::value(arg));
  102. }
  103. template<class Context, class Arg>
  104. static void apply(Context &ctx, const Arg &arg)
  105. {
  106. dispatch_apply(ctx, arg, typename proto::tag_of<Arg>::type());
  107. }
  108. };
  109. } // end detail namespace
  110. // get<N>()
  111. template<size_t N, class Arg>
  112. inline typename proto::result_of::make_expr<
  113. proto::tag::function, detail::get_func<N>, const Arg&
  114. >::type const
  115. get(const Arg &arg)
  116. {
  117. return proto::make_expr<proto::tag::function>(
  118. detail::get_func<N>(), ::boost::ref(arg)
  119. );
  120. }
  121. } // end lambda namespace
  122. } // end compute namespace
  123. } // end boost namespace
  124. #endif // BOOST_COMPUTE_LAMBDA_GET_HPP