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