• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ////////////////////////////////////////////////////////////////////////////
2 // lazy operator.hpp
3 //
4 // Build lazy operations for Phoenix equivalents for FC++
5 //
6 // These are equivalents of the Boost FC++ functoids in operator.hpp
7 //
8 // Implemented so far:
9 //
10 // make_pair
11 // plus minus multiplies divides modulus
12 // negate equal not_equal greater less
13 // greater_equal less_equal positive
14 // logical_and logical_or
15 // logical_not min max inc dec
16 //
17 // These are not from the FC++ operator.hpp but were made for testing purposes.
18 //
19 // identity (renamed id)
20 // sin
21 //
22 // These are now being modified to use boost::phoenix::function
23 // so that they are available for use as arguments.
24 // Types are being defined in capitals e.g. Id id;
25 ////////////////////////////////////////////////////////////////////////////
26 /*=============================================================================
27     Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
28     Copyright (c) 2001-2007 Joel de Guzman
29     Copyright (c) 2015 John Fletcher
30 
31     Distributed under the Boost Software License, Version 1.0. (See accompanying
32     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
33 ==============================================================================*/
34 
35 
36 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR
37 #define BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR
38 
39 #include <cmath>
40 #include <cstdlib>
41 #include <boost/phoenix/core.hpp>
42 #include <boost/phoenix/function.hpp>
43 #include <boost/function.hpp>
44 
45 namespace boost {
46 
47   namespace phoenix {
48 
49 //////////////////////////////////////////////////////////////////////
50 // a_unique_type_for_nil
51 //////////////////////////////////////////////////////////////////////
52 
53 // This may need to be moved elsewhere to define reuser.
54    struct a_unique_type_for_nil {
operator ==boost::phoenix::a_unique_type_for_nil55      bool operator==( a_unique_type_for_nil ) const { return true; }
operator <boost::phoenix::a_unique_type_for_nil56      bool operator< ( a_unique_type_for_nil ) const { return false; }
57      typedef a_unique_type_for_nil value_type;
58    };
59     // This maybe put into a namespace.
60    a_unique_type_for_nil NIL;
61 
62 //////////////////////////////////////////////////////////////////////
63 // lazy_exception - renamed from fcpp_exception.
64 //////////////////////////////////////////////////////////////////////
65 
66 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
67    struct lazy_exception : public std::exception {
68        const char* s;
lazy_exceptionboost::phoenix::lazy_exception69        lazy_exception( const char* ss ) : s(ss) {}
whatboost::phoenix::lazy_exception70        const char* what() const throw() { return s; }
71    };
72 #endif
73 
74 //////////////////////////////////////////////////////////////////////
75 
76    // in ref_count.hpp in BoostFC++
77    typedef unsigned int RefCountType;
78 
79     namespace impl {
80 
81       // Implemented early, moved from lazy_signature.hpp
82       template <class T>
83       struct remove_RC
84       {
85           typedef typename boost::remove_reference<T>::type TT;
86           typedef typename boost::remove_const<TT>::type type;
87       };
88 
89       struct XId
90       {
91         template <typename Sig>
92         struct result;
93 
94         template <typename This, typename A0>
95         struct result<This(A0)>
96            : boost::remove_reference<A0>
97         {};
98 
99         template <typename A0>
operator ()boost::phoenix::impl::XId100         A0 operator()(A0 const & a0) const
101         {
102             return a0;
103         }
104 
105       };
106 
107 
108     }
109 
110     typedef boost::phoenix::function<impl::XId> Id;
111     Id id;
112 
113 #ifdef BOOST_RESULT_OF_USE_TR1
114     // Experiment following examples in
115     // phoenix/stl/container/container.hpp
116 
117     namespace result_of {
118 
119       template <
120           typename Arg1
121         , typename Arg2
122       >
123       class make_pair
124       {
125       public:
126         typedef typename impl::remove_RC<Arg1>::type Arg1Type;
127         typedef typename impl::remove_RC<Arg2>::type Arg2Type;
128         typedef std::pair<Arg1Type,Arg2Type> type;
129         typedef std::pair<Arg1Type,Arg2Type> result_type;
130       };
131     }
132 #endif
133 
134   namespace impl
135   {
136 
137     struct XMake_pair {
138 
139 
140 #ifdef BOOST_RESULT_OF_USE_TR1
141        template <typename Sig>
142        struct result;
143        // This fails with -O2 unless refs are removed from A1 and A2.
144        template <typename This, typename A0, typename A1>
145        struct result<This(A0, A1)>
146        {
147          typedef typename result_of::make_pair<A0,A1>::type type;
148        };
149 #else
150        template <typename Sig>
151        struct result;
152 
153        template <typename This, typename A0, typename A1>
154        struct result<This(A0, A1)>
155          : boost::remove_reference<std::pair<A0, A1> >
156        {};
157 
158 #endif
159 
160 
161        template <typename A0, typename A1>
162 #ifdef BOOST_RESULT_OF_USE_TR1
163        typename result<XMake_pair(A0,A1)>::type
164 #else
165        std::pair<A0, A1>
166 #endif
operator ()boost::phoenix::impl::XMake_pair167        operator()(A0 const & a0, A1 const & a1) const
168        {
169           return std::make_pair(a0,a1);
170        }
171 
172     };
173   }
174 
175   typedef boost::phoenix::function<impl::XMake_pair> Make_pair;
176   Make_pair make_pair;
177 
178   namespace impl
179   {
180 
181     // For now I will leave the return type deduction as it is.
182     // I want to look at bringing in the sort of type deduction for
183     // mixed types which I have in FC++.
184     // Also I could look at the case where one of the arguments is
185     // another functor or a Phoenix placeholder.
186     struct XPlus
187     {
188         template <typename Sig>
189         struct result;
190 
191         template <typename This, typename A0, typename A1>
192         struct result<This(A0, A1)>
193              : boost::remove_reference<A0>
194         {};
195 
196         template <typename This, typename A0, typename A1, typename A2>
197         struct result<This(A0, A1, A2)>
198              : boost::remove_reference<A0>
199         {};
200 
201         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XPlus202         A0 operator()(A0 const & a0, A1 const & a1) const
203         {
204           //A0 res = a0 + a1;
205           //return res;
206           return a0 + a1;
207         }
208 
209         template <typename A0, typename A1, typename A2>
operator ()boost::phoenix::impl::XPlus210         A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const
211         {
212             return a0 + a1 + a2;
213         }
214     };
215 
216     struct XMinus
217     {
218         template <typename Sig>
219         struct result;
220 
221         template <typename This, typename A0, typename A1>
222         struct result<This(A0, A1)>
223            : boost::remove_reference<A0>
224         {};
225 
226         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XMinus227         A0 operator()(A0 const & a0, A1 const & a1) const
228         {
229             return a0 - a1;
230         }
231 
232     };
233 
234     struct XMultiplies
235     {
236         template <typename Sig>
237         struct result;
238 
239         template <typename This, typename A0, typename A1>
240         struct result<This(A0, A1)>
241            : boost::remove_reference<A0>
242         {};
243 
244         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XMultiplies245         A0 operator()(A0 const & a0, A1 const & a1) const
246         {
247             return a0 * a1;
248         }
249 
250     };
251 
252     struct XDivides
253     {
254         template <typename Sig>
255         struct result;
256 
257         template <typename This, typename A0, typename A1>
258         struct result<This(A0, A1)>
259            : boost::remove_reference<A0>
260         {};
261 
262         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XDivides263         A0 operator()(A0 const & a0, A1 const & a1) const
264         {
265             return a0 / a1;
266         }
267 
268     };
269 
270     struct XModulus
271     {
272         template <typename Sig>
273         struct result;
274 
275         template <typename This, typename A0, typename A1>
276         struct result<This(A0, A1)>
277           : boost::remove_reference<A0>
278         {};
279 
280         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XModulus281         A0 operator()(A0 const & a0, A1 const & a1) const
282         {
283             return a0 % a1;
284         }
285 
286     };
287 
288     struct XNegate
289     {
290         template <typename Sig>
291         struct result;
292 
293         template <typename This, typename A0>
294         struct result<This(A0)>
295            : boost::remove_reference<A0>
296         {};
297 
298         template <typename A0>
operator ()boost::phoenix::impl::XNegate299         A0 operator()(A0 const & a0) const
300         {
301             return -a0;
302         }
303     };
304 
305     struct XEqual
306     {
307         template <typename Sig>
308         struct result;
309 
310         template <typename This, typename A0, typename A1>
311         struct result<This(A0,A1)>
312         {
313             typedef bool type;
314         };
315 
316         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XEqual317         bool operator()(A0 const & a0, A1 const & a1) const
318         {
319             return a0 == a1;
320         }
321     };
322 
323     struct XNot_equal
324     {
325         template <typename Sig>
326         struct result;
327 
328         template <typename This, typename A0, typename A1>
329         struct result<This(A0,A1)>
330         {
331             typedef bool type;
332         };
333 
334         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XNot_equal335         bool operator()(A0 const & a0, A1 const & a1) const
336         {
337             return a0 != a1;
338         }
339     };
340 
341     struct XGreater
342     {
343         template <typename Sig>
344         struct result;
345 
346         template <typename This, typename A0, typename A1>
347         struct result<This(A0,A1)>
348         {
349             typedef bool type;
350         };
351 
352         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XGreater353         bool operator()(A0 const & a0, A1 const & a1) const
354         {
355             return a0 > a1;
356         }
357     };
358 
359     struct XLess
360     {
361         template <typename Sig>
362         struct result;
363 
364         template <typename This, typename A0, typename A1>
365         struct result<This(A0,A1)>
366         {
367             typedef bool type;
368         };
369 
370         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XLess371         bool operator()(A0 const & a0, A1 const & a1) const
372         {
373             return a0 < a1;
374         }
375     };
376 
377     struct XGreater_equal
378     {
379         template <typename Sig>
380         struct result;
381 
382         template <typename This, typename A0, typename A1>
383         struct result<This(A0,A1)>
384         {
385             typedef bool type;
386         };
387 
388         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XGreater_equal389         bool operator()(A0 const & a0, A1 const & a1) const
390         {
391             return a0 >= a1;
392         }
393     };
394 
395     struct XLess_equal
396     {
397         template <typename Sig>
398         struct result;
399 
400         template <typename This, typename A0, typename A1>
401         struct result<This(A0,A1)>
402         {
403             typedef bool type;
404         };
405 
406         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XLess_equal407         bool operator()(A0 const & a0, A1 const & a1) const
408         {
409             return a0 <= a1;
410         }
411     };
412 
413     struct XPositive
414     {
415         template <typename Sig>
416         struct result;
417 
418         template <typename This, typename A0>
419         struct result<This(A0)>
420         {
421             typedef bool type;
422         };
423 
424         template <typename A0>
operator ()boost::phoenix::impl::XPositive425         bool operator()(A0 const & a0) const
426         {
427           return a0 >= A0(0);
428         }
429     };
430 
431     struct XLogical_and
432     {
433         template <typename Sig>
434         struct result;
435 
436         template <typename This, typename A0, typename A1>
437         struct result<This(A0,A1)>
438         {
439             typedef bool type;
440         };
441 
442         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XLogical_and443         bool operator()(A0 const & a0, A1 const & a1) const
444         {
445             return a0 && a1;
446         }
447     };
448 
449     struct XLogical_or
450     {
451         template <typename Sig>
452         struct result;
453 
454         template <typename This, typename A0, typename A1>
455         struct result<This(A0,A1)>
456         {
457             typedef bool type;
458         };
459 
460         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XLogical_or461         bool operator()(A0 const & a0, A1 const & a1) const
462         {
463             return a0 || a1;
464         }
465     };
466 
467     struct XLogical_not
468     {
469         template <typename Sig>
470         struct result;
471 
472         template <typename This, typename A0>
473         struct result<This(A0)>
474         {
475              typedef bool type;
476         };
477 
478         template <typename A0>
operator ()boost::phoenix::impl::XLogical_not479         bool operator()(A0 const & a0) const
480         {
481             return !a0;
482         }
483     };
484 
485     struct XMin
486     {
487         template <typename Sig>
488         struct result;
489 
490         template <typename This, typename A0, typename A1>
491         struct result<This(A0, A1)>
492           : boost::remove_reference<A0>
493         {};
494 
495         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XMin496         A0 operator()(A0 const & a0, A1 const & a1) const
497         {
498            if ( a0 < a1 ) return a0; else return a1;
499         }
500 
501     };
502 
503     struct XMax
504     {
505         template <typename Sig>
506         struct result;
507 
508         template <typename This, typename A0, typename A1>
509         struct result<This(A0, A1)>
510           : boost::remove_reference<A0>
511         {};
512 
513         template <typename A0, typename A1>
operator ()boost::phoenix::impl::XMax514         A0 operator()(A0 const & a0, A1 const & a1) const
515         {
516            if ( a0 < a1 ) return a1; else return a0;
517         }
518 
519     };
520 
521     struct XInc
522     {
523         template <typename Sig>
524         struct result;
525 
526         template <typename This, typename A0>
527         struct result<This(A0)>
528            : boost::remove_reference<A0>
529         {};
530 
531         template <typename A0>
operator ()boost::phoenix::impl::XInc532         A0 operator()(A0 const & a0) const
533         {
534             return a0 + 1;
535         }
536 
537     };
538 
539     struct XDec
540     {
541         template <typename Sig>
542         struct result;
543 
544         template <typename This, typename A0>
545         struct result<This(A0)>
546            : boost::remove_reference<A0>
547         {};
548 
549         template <typename A0>
operator ()boost::phoenix::impl::XDec550         A0 operator()(A0 const & a0) const
551         {
552             return a0 - 1;
553         }
554 
555     };
556 
557     struct XSin
558     {
559         template <typename Sig>
560         struct result;
561 
562         template <typename This, typename A0>
563         struct result<This(A0)>
564            : boost::remove_reference<A0>
565         {};
566 
567         template <typename A0>
operator ()boost::phoenix::impl::XSin568         A0 operator()(A0 const & a0) const
569         {
570           return std::sin(a0);
571         }
572 
573     };
574 
575     // Example of templated struct.
576     // How do I make it callable?
577     template <typename Result>
578     struct what {
579 
580       typedef Result result_type;
581 
operator ()boost::phoenix::impl::what582       Result operator()(Result const & r) const
583       {
584         return r;
585       }
586       // what is not complete - error.
587       //static boost::function1<Result,Result> res = what<Result>();
588     };
589 
590     template <typename Result>
591     struct what0 {
592 
593       typedef Result result_type;
594 
operator ()boost::phoenix::impl::what0595       Result operator()() const
596       {
597         return Result(100);
598       }
599 
600     };
601 
602 
603       template <class Result, class F>
604       class MonomorphicWrapper0 /* : public c_fun_type<Res> */
605       {
606           F f;
607       public:
608           typedef Result result_type;
MonomorphicWrapper0(const F & g)609           MonomorphicWrapper0( const F& g ) : f(g) {}
operator ()() const610              Result operator()() const {
611              return f();
612           }
613       };
614 
615   }
616     /////////////////////////////////////////////////////////
617     // Look at this. How to use Phoenix with a templated
618     // struct. First adapt with boost::function and then
619     // convert that to Phoenix!!
620     // I have not found out how to do it directly.
621     /////////////////////////////////////////////////////////
622 boost::function1<int, int > what_int = impl::what<int>();
623 typedef boost::function1<int,int> fun1_int_int;
624 typedef boost::function0<int> fun0_int;
625 boost::function0<int> what0_int = impl::what0<int>();
626 BOOST_PHOENIX_ADAPT_FUNCTION(int,what,what_int,1)
627 BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int,what0,what0_int)
628 // And this shows how to make them into argument callable functions.
629 typedef boost::phoenix::function<fun1_int_int> What_arg;
630 typedef boost::phoenix::function<fun0_int> What0_arg;
631 What_arg what_arg(what_int);
632 What0_arg what0_arg(what0_int);
633 
634 
635 // To use these as arguments they have to be defined like this.
636     typedef boost::phoenix::function<impl::XPlus> Plus;
637     typedef boost::phoenix::function<impl::XMinus> Minus;
638     typedef boost::phoenix::function<impl::XMultiplies> Multiplies;
639     typedef boost::phoenix::function<impl::XDivides>   Divides;
640     typedef boost::phoenix::function<impl::XModulus>   Modulus;
641     typedef boost::phoenix::function<impl::XNegate>    Negate;
642     typedef boost::phoenix::function<impl::XEqual>     Equal;
643     typedef boost::phoenix::function<impl::XNot_equal> Not_equal;
644     typedef boost::phoenix::function<impl::XGreater>   Greater;
645     typedef boost::phoenix::function<impl::XLess>      Less;
646     typedef boost::phoenix::function<impl::XGreater_equal> Greater_equal;
647     typedef boost::phoenix::function<impl::XLess_equal>    Less_equal;
648     typedef boost::phoenix::function<impl::XPositive>    Positive;
649     typedef boost::phoenix::function<impl::XLogical_and> Logical_and;
650     typedef boost::phoenix::function<impl::XLogical_or>  Logical_or;
651     typedef boost::phoenix::function<impl::XLogical_not> Logical_not;
652     typedef boost::phoenix::function<impl::XMax> Max;
653     typedef boost::phoenix::function<impl::XMin> Min;
654     typedef boost::phoenix::function<impl::XInc> Inc;
655     typedef boost::phoenix::function<impl::XDec> Dec;
656     typedef boost::phoenix::function<impl::XSin> Sin;
657     Plus plus;
658     Minus minus;
659     Multiplies multiplies;
660     Divides divides;
661     Modulus modulus;
662     Negate  negate;
663     Equal   equal;
664     Not_equal not_equal;
665     Greater greater;
666     Less    less;
667     Greater_equal greater_equal;
668     Less_equal    less_equal;
669     Positive      positive;
670     Logical_and   logical_and;
671     Logical_or    logical_or;
672     Logical_not   logical_not;
673     Max max;
674     Min min;
675     Inc inc;
676     Dec dec;
677     Sin sin;
678 }
679 
680 }
681 
682 
683 #endif
684