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