lazy_smart.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. ////////////////////////////////////////////////////////////////////////////
  2. // lazy smart.hpp
  3. //
  4. // Build lazy functoid traits for Phoenix equivalents for FC++
  5. //
  6. // These are equivalents of the Boost FC++ functoid traits in smart.hpp
  7. //
  8. // I have copied the versions for zero, one, two and three arguments.
  9. //
  10. /*=============================================================================
  11. Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
  12. Copyright (c) 2001-2007 Joel de Guzman
  13. Copyright (c) 2015 John Fletcher
  14. Distributed under the Boost Software License, Version 1.0. (See accompanying
  15. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  16. ==============================================================================*/
  17. #ifndef BOOST_PHOENIX_FUNCTION_LAZY_SMART
  18. #define BOOST_PHOENIX_FUNCTION_LAZY_SMART
  19. namespace boost {
  20. namespace phoenix {
  21. namespace fcpp {
  22. //////////////////////////////////////////////////////////////////////
  23. // Feature: Smartness
  24. //////////////////////////////////////////////////////////////////////
  25. // If F is smart, then we can refer to these entities:
  26. //
  27. // functoid_traits<F>::template accepts<N>::args
  28. // A bool which says whether F can accept N arguments
  29. //
  30. // functoid_traits<F>::max_args
  31. // An int which says what the most arguments F can accept is
  32. //
  33. // functoid_traits<F>::template ensure_accepts<N>::args()
  34. // A no-op call that compiles only if F can accept N args
  35. //
  36. // We use traits so that if you happen to ask a non-smart functoid these
  37. // questions, you will hopefully get a literate error message.
  38. struct SmartFunctoid {};
  39. // We add crazy identifiers to ensure that users don't accidentally talk
  40. // to functoids directly; they should always be going through the traits
  41. // class to ask for info.
  42. struct smart_functoid0 : public SmartFunctoid {
  43. template <class Dummy, int i> struct crazy_accepts {
  44. static const bool args = false;
  45. };
  46. template <class Dummy> struct crazy_accepts<Dummy,0> {
  47. static const bool args = true;
  48. };
  49. static const int crazy_max_args = 0;
  50. };
  51. struct smart_functoid1 : public SmartFunctoid {
  52. template <class Dummy, int i> struct crazy_accepts {
  53. static const bool args = false;
  54. };
  55. template <class Dummy> struct crazy_accepts<Dummy,1> {
  56. static const bool args = true;
  57. };
  58. static const int crazy_max_args = 1;
  59. };
  60. struct smart_functoid2 : public SmartFunctoid {
  61. template <class Dummy, int i> struct crazy_accepts {
  62. static const bool args = false;
  63. };
  64. template <class Dummy> struct crazy_accepts<Dummy,1> {
  65. static const bool args = true;
  66. };
  67. template <class Dummy> struct crazy_accepts<Dummy,2> {
  68. static const bool args = true;
  69. };
  70. static const int crazy_max_args = 2;
  71. };
  72. struct smart_functoid3 : public SmartFunctoid {
  73. template <class Dummy, int i> struct crazy_accepts {
  74. static const bool args = false;
  75. };
  76. template <class Dummy> struct crazy_accepts<Dummy,1> {
  77. static const bool args = true;
  78. };
  79. template <class Dummy> struct crazy_accepts<Dummy,2> {
  80. static const bool args = true;
  81. };
  82. template <class Dummy> struct crazy_accepts<Dummy,3> {
  83. static const bool args = true;
  84. };
  85. static const int crazy_max_args = 3;
  86. };
  87. namespace impl {
  88. template <class F, bool b> struct NeededASmartFunctoidButInsteadGot {};
  89. template <class F> struct NeededASmartFunctoidButInsteadGot<F,true> {
  90. typedef F type;
  91. };
  92. template <bool b> struct Ensure;
  93. template <> struct Ensure<true> {};
  94. } // end namespace impl
  95. template <class MaybeASmartFunctoid>
  96. struct functoid_traits {
  97. typedef typename boost::remove_reference<MaybeASmartFunctoid>::type MaybeASmartFunctoidT;
  98. typedef
  99. typename impl::NeededASmartFunctoidButInsteadGot<MaybeASmartFunctoidT,
  100. boost::is_base_and_derived<SmartFunctoid,
  101. MaybeASmartFunctoidT>::value>::type F;
  102. template <int i> struct accepts {
  103. static const bool args = F::template crazy_accepts<int,i>::args;
  104. };
  105. template <int i> struct ensure_accepts {
  106. static const bool ok = F::template crazy_accepts<int,i>::args;
  107. inline static void args() { (void) impl::Ensure<ok>(); }
  108. };
  109. static const int max_args = F::crazy_max_args;
  110. };
  111. // These can be used to make functoids smart without having to alter
  112. // code elsewhere. These are used instead of boost::phoenix::function
  113. // to declare the object.
  114. template <typename F>
  115. struct smart_function0 : public smart_functoid0,
  116. public boost::phoenix::function<F>
  117. { };
  118. template <typename F>
  119. struct smart_function1 : public smart_functoid1,
  120. public boost::phoenix::function<F>
  121. {
  122. typedef F type;
  123. };
  124. template <typename F>
  125. struct smart_function2 : public smart_functoid2,
  126. public boost::phoenix::function<F>
  127. { };
  128. template <typename F>
  129. struct smart_function3 : public smart_functoid3,
  130. public boost::phoenix::function<F>
  131. { };
  132. }
  133. }
  134. }
  135. #endif