• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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