operator.qbk 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. [/==============================================================================
  2. Copyright (C) 2001-2010 Joel de Guzman
  3. Copyright (C) 2001-2005 Dan Marsden
  4. Copyright (C) 2001-2010 Thomas Heller
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ===============================================================================/]
  8. [section Operator]
  9. #include <boost/phoenix/operator.hpp>
  10. This facility provides a mechanism for lazily evaluating operators.
  11. Syntactically, a lazy operator looks and feels like an ordinary C/C++ infix,
  12. prefix or postfix operator. The operator application looks the same. However,
  13. unlike ordinary operators, the actual operator execution is deferred. Samples:
  14. arg1 + arg2
  15. 1 + arg1 * arg2
  16. 1 / -arg1
  17. arg1 < 150
  18. We have seen the lazy operators in action (see [link phoenix.starter_kit.lazy_operators
  19. Quick Start - Lazy Operators]). Let's go back and examine them a little bit further:
  20. std::find_if(c.begin(), c.end(), arg1 % 2 == 1)
  21. Through operator overloading, the expression `arg1 % 2 == 1` actually generates
  22. an actor. This actor object is passed on to STL's `find_if` function. From
  23. the viewpoint of STL, the expression is simply a function object expecting a
  24. single argument of the containers value_type. For each element in `c`,
  25. the element is passed on as an argument `arg1` to the actor (function
  26. object). The actor checks if this is an odd value based on the expression
  27. `arg1 % 2 == 1` where arg1 is replaced by the container's element.
  28. Like lazy functions (see
  29. [link phoenix.modules.function Function]), lazy operators are not immediately executed
  30. when invoked. Instead, an actor (see [link phoenix.actor Actor])
  31. object is created and returned to the caller. Example:
  32. (arg1 + arg2) * arg3
  33. does nothing more than return an actor. A second function call will evaluate
  34. the actual operators. Example:
  35. std::cout << ((arg1 + arg2) * arg3)(4, 5, 6);
  36. will print out "54".
  37. Operator expressions are lazily evaluated following four simple rules:
  38. # A binary operator, except `->*` will be lazily evaluated when
  39. /at least/ one of its operands is an actor object
  40. (see [link phoenix.actor Actor]).
  41. # Unary operators are lazily evaluated if their argument is an actor object.
  42. # Operator `->*` is lazily evaluated if the left hand argument is an actor object.
  43. # The result of a lazy operator is an actor object that can in turn allow the
  44. applications of rules 1, 2 and 3.
  45. For example, to check the following expression is lazily evaluated:
  46. -(arg1 + 3 + 6)
  47. # Following rule 1, `arg1 + 3` is lazily evaluated since `arg1` is an actor
  48. (see [link phoenix.modules.core.arguments Arguments]).
  49. # The result of this `arg1 + 3` expression is an actor object, following rule 4.
  50. # Continuing, `arg1 + 3 + 6` is again lazily evaluated.
  51. Rule 2.
  52. # By rule 4 again, the result of `arg1 + 3 + 6` is an actor object.
  53. # As `arg1 + 3 + 6` is an actor, `-(arg1 + 3 + 6)` is lazily evaluated. Rule 2.
  54. Lazy-operator application is highly contagious. In most cases, a single `argN`
  55. actor infects all its immediate neighbors within a group (first level or
  56. parenthesized expression).
  57. Note that at least one operand of any operator must be a valid actor
  58. for lazy evaluation to take effect. To force lazy evaluation of an
  59. ordinary expression, we can use `ref(x)`, `val(x)` or `cref(x)` to
  60. transform an operand into a valid actor object (see [link phoenix.modules.core Core]).
  61. For example:
  62. 1 << 3; // Immediately evaluated
  63. val(1) << 3; // Lazily evaluated
  64. [heading Supported operators]
  65. [heading Unary operators]
  66. prefix: ~, !, -, +, ++, --, & (reference), * (dereference)
  67. postfix: ++, --
  68. [heading Binary operators]
  69. =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  70. +, -, *, /, %, &, |, ^, <<, >>
  71. ==, !=, <, >, <=, >=
  72. &&, ||, ->*
  73. [heading Ternary operator]
  74. if_else(c, a, b)
  75. The ternary operator deserves special mention. Since C++ does not allow us to
  76. overload the conditional expression: `c ? a : b`, the if_else pseudo function is
  77. provided for this purpose. The behavior is identical, albeit in a lazy manner.
  78. [heading Member pointer operator]
  79. a->*member_object_pointer
  80. a->*member_function_pointer
  81. The left hand side of the member pointer operator must be an actor returning a pointer
  82. type. The right hand side of the member pointer operator may be either a pointer to member
  83. object or pointer to member function.
  84. If the right hand side is a member object pointer, the result is an actor which, when evaluated,
  85. returns a reference to that member. For example:
  86. struct A
  87. {
  88. int member;
  89. };
  90. A* a = new A;
  91. ...
  92. (arg1->*&A::member)(a); // returns member a->member
  93. If the right hand side is a member function pointer, the result is an actor which, when invoked, calls the specified member function. For example:
  94. struct A
  95. {
  96. int func(int);
  97. };
  98. A* a = new A;
  99. int i = 0;
  100. (arg1->*&A::func)(arg2)(a, i); // returns a->func(i)
  101. [heading Include Files]
  102. [table
  103. [[Operators] [File]]
  104. [[`-`, `+`, `++`, `--`, `+=`,
  105. `-=`, `*=`, `/=`, `%=`,
  106. `*`, `/`, `%`] [`#include <boost/phoenix/operator/arithmetic.hpp>`]]
  107. [[`&=`, `|=`, `^=`, `<<=`,
  108. `>>=`, `&`, `|`, `^`, `<<`,
  109. `>>`] [`#include <boost/phoenix/operator/bitwise.hpp>`]]
  110. [[`==`, `!=`, `<`,
  111. `<=`, `>`, `>=`] [`#include <boost/phoenix/operator/comparison.hpp>`]]
  112. [[`<<`, `>>`] [`#include <boost/phoenix/operator/io.hpp>`]]
  113. [[`!`, &&, `||`] [`#include <boost/phoenix/operator/logical.hpp>`]]
  114. [[`&x`, `*p`, `=`, `[]`] [`#include <boost/phoenix/operator/self.hpp>`]]
  115. [[`if_else(c, a, b)`] [`#include <boost/phoenix/operator/if_else.hpp>`]]
  116. [[`->*`] [`#include <boost/phoenix/operator/member.hpp>`]]
  117. ]
  118. [endsect]