lambda_functors.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Boost Lambda Library - lambda_functors.hpp -------------------------------
  2. // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see http://www.boost.org
  9. // ------------------------------------------------
  10. #ifndef BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
  11. #define BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP
  12. #include <boost/config.hpp>
  13. #include <boost/detail/workaround.hpp>
  14. #include <boost/utility/result_of.hpp>
  15. #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  16. #include <boost/mpl/or.hpp>
  17. #include <boost/utility/enable_if.hpp>
  18. #include <boost/type_traits/is_array.hpp>
  19. #define BOOST_LAMBDA_DISABLE_IF_ARRAY1(A1, R1)\
  20. typename lazy_disable_if<is_array<A1>, typename R1 >::type
  21. #define BOOST_LAMBDA_DISABLE_IF_ARRAY2(A1, A2, R1, R2) \
  22. typename lazy_disable_if<mpl::or_<is_array<A1>, is_array<A2> >, typename R1, R2 >::type
  23. #define BOOST_LAMBDA_DISABLE_IF_ARRAY3(A1, A2, A3, R1, R2, R3) \
  24. typename lazy_disable_if<mpl::or_<is_array<A1>, is_array<A2>, is_array<A3> >, typename R1, R2, R3 >::type
  25. #else
  26. #define BOOST_LAMBDA_DISABLE_IF_ARRAY1(A1, R1) typename R1::type
  27. #define BOOST_LAMBDA_DISABLE_IF_ARRAY2(A1, A2, R1, R2) typename R1, R2::type
  28. #define BOOST_LAMBDA_DISABLE_IF_ARRAY3(A1, A2, A3, R1, R2, R3) typename R1, R2, R3::type
  29. #endif
  30. namespace boost {
  31. namespace lambda {
  32. // -- lambda_functor --------------------------------------------
  33. // --------------------------------------------------------------
  34. //inline const null_type const_null_type() { return null_type(); }
  35. namespace detail {
  36. namespace {
  37. static const null_type constant_null_type = null_type();
  38. } // unnamed
  39. } // detail
  40. class unused {};
  41. #define cnull_type() detail::constant_null_type
  42. // -- free variables types --------------------------------------------------
  43. // helper to work around the case where the nullary return type deduction
  44. // is always performed, even though the functor is not nullary
  45. namespace detail {
  46. template<int N, class Tuple> struct get_element_or_null_type {
  47. typedef typename
  48. detail::tuple_element_as_reference<N, Tuple>::type type;
  49. };
  50. template<int N> struct get_element_or_null_type<N, null_type> {
  51. typedef null_type type;
  52. };
  53. }
  54. template <int I> struct placeholder;
  55. template<> struct placeholder<FIRST> {
  56. template<class SigArgs> struct sig {
  57. typedef typename detail::get_element_or_null_type<0, SigArgs>::type type;
  58. };
  59. template<class RET, CALL_TEMPLATE_ARGS>
  60. RET call(CALL_FORMAL_ARGS) const {
  61. BOOST_STATIC_ASSERT(boost::is_reference<RET>::value);
  62. CALL_USE_ARGS; // does nothing, prevents warnings for unused args
  63. return a;
  64. }
  65. };
  66. template<> struct placeholder<SECOND> {
  67. template<class SigArgs> struct sig {
  68. typedef typename detail::get_element_or_null_type<1, SigArgs>::type type;
  69. };
  70. template<class RET, CALL_TEMPLATE_ARGS>
  71. RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return b; }
  72. };
  73. template<> struct placeholder<THIRD> {
  74. template<class SigArgs> struct sig {
  75. typedef typename detail::get_element_or_null_type<2, SigArgs>::type type;
  76. };
  77. template<class RET, CALL_TEMPLATE_ARGS>
  78. RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return c; }
  79. };
  80. template<> struct placeholder<EXCEPTION> {
  81. template<class SigArgs> struct sig {
  82. typedef typename detail::get_element_or_null_type<3, SigArgs>::type type;
  83. };
  84. template<class RET, CALL_TEMPLATE_ARGS>
  85. RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return env; }
  86. };
  87. typedef const lambda_functor<placeholder<FIRST> > placeholder1_type;
  88. typedef const lambda_functor<placeholder<SECOND> > placeholder2_type;
  89. typedef const lambda_functor<placeholder<THIRD> > placeholder3_type;
  90. ///////////////////////////////////////////////////////////////////////////////
  91. // free variables are lambda_functors. This is to allow uniform handling with
  92. // other lambda_functors.
  93. // -------------------------------------------------------------------
  94. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  95. #pragma warning(push)
  96. #pragma warning(disable:4512) //assignment operator could not be generated
  97. #endif
  98. // -- lambda_functor NONE ------------------------------------------------
  99. template <class T>
  100. class lambda_functor : public T
  101. {
  102. BOOST_STATIC_CONSTANT(int, arity_bits = get_arity<T>::value);
  103. public:
  104. typedef T inherited;
  105. lambda_functor() {}
  106. lambda_functor(const lambda_functor& l) : inherited(l) {}
  107. lambda_functor(const T& t) : inherited(t) {}
  108. template <class SigArgs> struct sig {
  109. typedef typename inherited::template
  110. sig<typename SigArgs::tail_type>::type type;
  111. };
  112. // Note that this return type deduction template is instantiated, even
  113. // if the nullary
  114. // operator() is not called at all. One must make sure that it does not fail.
  115. typedef typename
  116. inherited::template sig<null_type>::type
  117. nullary_return_type;
  118. // Support for boost::result_of.
  119. template <class Sig> struct result;
  120. template <class F>
  121. struct result<F()> {
  122. typedef nullary_return_type type;
  123. };
  124. template <class F, class A>
  125. struct result<F(A)> {
  126. typedef typename sig<tuple<F, A> >::type type;
  127. };
  128. template <class F, class A, class B>
  129. struct result<F(A, B)> {
  130. typedef typename sig<tuple<F, A, B> >::type type;
  131. };
  132. template <class F, class A, class B, class C>
  133. struct result<F(A, B, C)> {
  134. typedef typename sig<tuple<F, A, B, C> >::type type;
  135. };
  136. nullary_return_type operator()() const {
  137. return inherited::template
  138. call<nullary_return_type>
  139. (cnull_type(), cnull_type(), cnull_type(), cnull_type());
  140. }
  141. template<class A>
  142. typename inherited::template sig<tuple<A&> >::type
  143. operator()(A& a) const {
  144. return inherited::template call<
  145. typename inherited::template sig<tuple<A&> >::type
  146. >(a, cnull_type(), cnull_type(), cnull_type());
  147. }
  148. template<class A>
  149. BOOST_LAMBDA_DISABLE_IF_ARRAY1(A, inherited::template sig<tuple<A const&> >)
  150. operator()(A const& a) const {
  151. return inherited::template call<
  152. typename inherited::template sig<tuple<A const&> >::type
  153. >(a, cnull_type(), cnull_type(), cnull_type());
  154. }
  155. template<class A, class B>
  156. typename inherited::template sig<tuple<A&, B&> >::type
  157. operator()(A& a, B& b) const {
  158. return inherited::template call<
  159. typename inherited::template sig<tuple<A&, B&> >::type
  160. >(a, b, cnull_type(), cnull_type());
  161. }
  162. template<class A, class B>
  163. BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A const&, B&> >)
  164. operator()(A const& a, B& b) const {
  165. return inherited::template call<
  166. typename inherited::template sig<tuple<A const&, B&> >::type
  167. >(a, b, cnull_type(), cnull_type());
  168. }
  169. template<class A, class B>
  170. BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A&, B const&> >)
  171. operator()(A& a, B const& b) const {
  172. return inherited::template call<
  173. typename inherited::template sig<tuple<A&, B const&> >::type
  174. >(a, b, cnull_type(), cnull_type());
  175. }
  176. template<class A, class B>
  177. BOOST_LAMBDA_DISABLE_IF_ARRAY2(A, B, inherited::template sig<tuple<A const&, B const&> >)
  178. operator()(A const& a, B const& b) const {
  179. return inherited::template call<
  180. typename inherited::template sig<tuple<A const&, B const&> >::type
  181. >(a, b, cnull_type(), cnull_type());
  182. }
  183. template<class A, class B, class C>
  184. typename inherited::template sig<tuple<A&, B&, C&> >::type
  185. operator()(A& a, B& b, C& c) const
  186. {
  187. return inherited::template call<
  188. typename inherited::template sig<tuple<A&, B&, C&> >::type
  189. >(a, b, c, cnull_type());
  190. }
  191. template<class A, class B, class C>
  192. BOOST_LAMBDA_DISABLE_IF_ARRAY3(A, B, C, inherited::template sig<tuple<A const&, B const&, C const&> >)
  193. operator()(A const& a, B const& b, C const& c) const
  194. {
  195. return inherited::template call<
  196. typename inherited::template sig<tuple<A const&, B const&, C const&> >::type
  197. >(a, b, c, cnull_type());
  198. }
  199. // for internal calls with env
  200. template<CALL_TEMPLATE_ARGS>
  201. typename inherited::template sig<tuple<CALL_REFERENCE_TYPES> >::type
  202. internal_call(CALL_FORMAL_ARGS) const {
  203. return inherited::template
  204. call<typename inherited::template
  205. sig<tuple<CALL_REFERENCE_TYPES> >::type>(CALL_ACTUAL_ARGS);
  206. }
  207. template<class A>
  208. const lambda_functor<lambda_functor_base<
  209. other_action<assignment_action>,
  210. boost::tuple<lambda_functor,
  211. typename const_copy_argument <const A>::type> > >
  212. operator=(const A& a) const {
  213. return lambda_functor_base<
  214. other_action<assignment_action>,
  215. boost::tuple<lambda_functor,
  216. typename const_copy_argument <const A>::type> >
  217. ( boost::tuple<lambda_functor,
  218. typename const_copy_argument <const A>::type>(*this, a) );
  219. }
  220. template<class A>
  221. const lambda_functor<lambda_functor_base<
  222. other_action<subscript_action>,
  223. boost::tuple<lambda_functor,
  224. typename const_copy_argument <const A>::type> > >
  225. operator[](const A& a) const {
  226. return lambda_functor_base<
  227. other_action<subscript_action>,
  228. boost::tuple<lambda_functor,
  229. typename const_copy_argument <const A>::type> >
  230. ( boost::tuple<lambda_functor,
  231. typename const_copy_argument <const A>::type>(*this, a ) );
  232. }
  233. };
  234. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  235. #pragma warning(pop)
  236. #endif
  237. } // namespace lambda
  238. } // namespace boost
  239. namespace boost {
  240. #if !defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_NO_CXX11_DECLTYPE)
  241. template<class T>
  242. struct result_of<boost::lambda::lambda_functor<T>()>
  243. {
  244. typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
  245. };
  246. template<class T>
  247. struct result_of<const boost::lambda::lambda_functor<T>()>
  248. {
  249. typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
  250. };
  251. #endif
  252. template<class T>
  253. struct tr1_result_of<boost::lambda::lambda_functor<T>()>
  254. {
  255. typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
  256. };
  257. template<class T>
  258. struct tr1_result_of<const boost::lambda::lambda_functor<T>()>
  259. {
  260. typedef typename boost::lambda::lambda_functor<T>::nullary_return_type type;
  261. };
  262. }
  263. // is_placeholder
  264. #include <boost/is_placeholder.hpp>
  265. namespace boost
  266. {
  267. template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::FIRST> > >
  268. {
  269. enum _vt { value = 1 };
  270. };
  271. template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::SECOND> > >
  272. {
  273. enum _vt { value = 2 };
  274. };
  275. template<> struct is_placeholder< lambda::lambda_functor< lambda::placeholder<lambda::THIRD> > >
  276. {
  277. enum _vt { value = 3 };
  278. };
  279. } // namespace boost
  280. #endif