[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]
![]() |
vigra/functorexpression.hxx | ![]() |
---|
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.4.0, Dec 21 2005 ) */ 00008 /* The VIGRA Website is */ 00009 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00010 /* Please direct questions, bug reports, and contributions to */ 00011 /* koethe@informatik.uni-hamburg.de or */ 00012 /* vigra@kogs1.informatik.uni-hamburg.de */ 00013 /* */ 00014 /* Permission is hereby granted, free of charge, to any person */ 00015 /* obtaining a copy of this software and associated documentation */ 00016 /* files (the "Software"), to deal in the Software without */ 00017 /* restriction, including without limitation the rights to use, */ 00018 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00019 /* sell copies of the Software, and to permit persons to whom the */ 00020 /* Software is furnished to do so, subject to the following */ 00021 /* conditions: */ 00022 /* */ 00023 /* The above copyright notice and this permission notice shall be */ 00024 /* included in all copies or substantial portions of the */ 00025 /* Software. */ 00026 /* */ 00027 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00028 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00029 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00030 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00031 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00032 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00033 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00034 /* OTHER DEALINGS IN THE SOFTWARE. */ 00035 /* */ 00036 /************************************************************************/ 00037 00038 #ifndef VIGRA_FUNCTOREXPRESSION_HXX 00039 #define VIGRA_FUNCTOREXPRESSION_HXX 00040 00041 00042 /** \page FunctorExpressions Functor Expressions 00043 00044 Simple automatic functor creation by means of expression templates 00045 (also known as a "lambda library"). 00046 00047 <b>\#include</b> "<a href="functorexpression_8hxx-source.html">vigra/functorexpression.hxx</a>"<br> 00048 Namespace: vigra::functor 00049 00050 <b> Note:</b> This functionality is not available under Microsoft Visual C++, 00051 because support for partial template specialization is required. 00052 00053 <b> Motivation</b> 00054 00055 Many generic algorithms are made more flexible by means of functors 00056 which define part of the algorithms' behavior according to the 00057 needs of a specific situation. For example, we can apply an exponential 00058 to each pixel by passing a pointer to the <TT>exp</TT> function 00059 to <TT>transformImage()</TT>: 00060 00061 \code 00062 vigra::FImage src(w,h), dest(w,h); 00063 ... // fill src 00064 00065 vigra::transformImage(srcImageRange(src), destImage(dest), &exp); 00066 \endcode 00067 00068 However, this only works for simple operations. If we wanted to 00069 apply the exponential to a scaled pixel value (i.e. we want to execute 00070 <TT>exp(-beta*v)</TT>), we first need to implement a new functor: 00071 00072 \code 00073 struct Exponential 00074 { 00075 Exponential(double b) 00076 : beta(b) 00077 {} 00078 00079 template <class PixelType> 00080 PixelType operator()(PixelType const& v) const 00081 { 00082 return exp(-beta*v); 00083 } 00084 00085 double beta; 00086 }; 00087 \endcode 00088 00089 This functor would be used like this: 00090 00091 \code 00092 double beta = ...; 00093 vigra::transformImage(srcImageRange(src), destImage(dest), 00094 Exponential(beta)); 00095 \endcode 00096 00097 However, this approach has some disadvantages: 00098 00099 <UL> 00100 00101 <li> Writing a functor is more work then simply programm the loop 00102 directly, i.e. non-generically. Programmers will tend to 00103 avoid generic constructs, if they require so much writing. 00104 <li> Often, functors are only needed for a single expression. 00105 It is not desirable to get into the trouble of introducing 00106 and documenting a new class if that class is used only once. 00107 <li> Functors cannot be implemented directly at the point of use. 00108 Thus, to find out exactly what a functor is doing, one needs 00109 to look somewhere else. This complicates use and maintainance 00110 ot generic code. 00111 00112 </UL> 00113 00114 Therefore, it is necessary to provide a means to generate functors on 00115 the fly where they are needed. The C++ standard library contains so called 00116 "functor combinators" that allow to construct complicated functors from 00117 simpler ones. The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" 00118 would be solved like this: 00119 00120 \code 00121 float beta = ...; 00122 00123 vigra::transformImage(srcImageRange(src), destImage(dest), 00124 std::compose1(std::ptr_fun(exp), 00125 std::bind1st(std::multiplies<float>(), -beta))); 00126 \endcode 00127 00128 I won't go into details on how this works. Suffice it to say that 00129 this technique requires a functional programming style that is unfamiliar 00130 to many programmers, and thus leads to code that is difficult to 00131 understand. Moreover, this technique has some limitations that prevent 00132 certain expressions from being implementable this way. Therefore, VIGRA 00133 provides a better and simpler means to create functors on the fly. 00134 00135 <b> Automatic Functor Creation</b> 00136 00137 Automatic functor creation in VIGRA is based on a technique called 00138 <a href="http://extreme.indiana.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">Expression Templates</a>. 00139 This means that C++ operators are 00140 overloaded so that they don't execute the specified operation directly, 00141 but instead produce a functor which will later calculate the result. 00142 This technique has the big advantage that the familiar operator notation 00143 can be used, while all the flexibility of generic programming is preserved. 00144 Unfortunately, it requires partial template specialization, so these capabilities 00145 are not available on compilers that dont support this C++ feature 00146 (in particular, on Microsoft Visual C++). 00147 00148 The above problem "apply <TT>exp(-beta*v)</TT> to every pixel" will be solved 00149 like this: 00150 00151 \code 00152 using namespace vigra::functor; 00153 00154 float beta = ...; 00155 00156 transformImage(srcImageRange(src), destImage(dest), 00157 exp(Param(-beta)*Arg1())); 00158 \endcode 00159 00160 Here, four expression templates have been used to create the desired 00161 functor: 00162 00163 <DL> 00164 00165 <DT><b><TT>Param(-beta):</TT></b><DD> creates a functor that represents a 00166 constant (<TT>-beta</TT> in this case) 00167 00168 <DT><b><TT>Arg1():</TT></b><DD> represents the first argument of the expression (i.e. 00169 the pixels of image <TT>src</TT> in the example). Likewise, <TT>Arg2()</TT> and 00170 <TT>Arg3()</TT> are defined to represent more arguments. These are needed 00171 for algorithms that have multiple input images, such as 00172 \ref combineTwoImages() and \ref combineThreeImages(). 00173 00174 <DT><b>* (multiplication):</b><DD> creates a functor that returns the product of 00175 its arguments. Likewise, the other C++ operators (i.e. 00176 <TT>+, -, *, /, %, ==, !=, <, <=, >, >=, &&, ||, &, |, ^, !, ~</TT>) 00177 are overloaded. 00178 00179 <DT><b><TT>exp():</TT></b><DD> creates a functor that takes the exponential of its 00180 argument. Likewise, the other algebraic functions 00181 (i.e. <TT>sqrt, exp, log, log10, sin, asin, cos, acos, tan, 00182 atan, abs, floor, ceil, pow, atan2, fmod, min, max</TT>) 00183 are overloaded. 00184 00185 </DL> 00186 00187 We will explain additional capabilities of the functor creation mechanism 00188 by means of examples. 00189 00190 The same argument can be used several times in the expression. 00191 For example, to calculate the gradient magnitude from the components 00192 of the gradient vector, you may write: 00193 00194 \code 00195 using namespace vigra::functor; 00196 00197 vigra::FImage gradient_x(w,h), gradient_y(w,h), magnitude(w,h); 00198 ... // calculate gradient_x and gradient_y 00199 00200 combineTwoImages(srcImageRange(gradient_x), srcImage(gradient_y), 00201 destImage(magnitude), 00202 sqrt(Arg1()*Arg1() + Arg2()*Arg2())); 00203 \endcode 00204 00205 It is also possible to build other functions into functor expressions. Suppose 00206 you want to apply <TT>my_complicated_function()</TT> to the sum of two images: 00207 00208 \code 00209 using namespace vigra::functor; 00210 00211 vigra::FImage src1(w,h), src2(w,h), dest(w,h); 00212 00213 double my_complicated_function(double); 00214 00215 combineTwoImages(srcImageRange(src1), srcImage(src2), destImage(dest), 00216 applyFct(&my_complicated_function, Arg1()+Arg2())); 00217 \endcode 00218 00219 [Note that the arguments of the wrapped function are passed as additional 00220 arguments to <TT>applyFct()</TT>] 00221 00222 You can implement conditional expression by means of the <TT>ifThenElse()</TT> 00223 functor. It corresponds to the "? :" operator that cannot be overloaded. 00224 <TT>ifThenElse()</TT> can be used, for example, to threshold an image: 00225 00226 \code 00227 using namespace vigra::functor; 00228 00229 vigra::FImage src(w,h), thresholded(w,h); 00230 ...// fill src 00231 00232 float threshold = ...; 00233 00234 transformImage(srcImageRange(src), destImage(thresholded), 00235 ifThenElse(Arg1() < Param(threshold), 00236 Param(0.0), // yes branch 00237 Param(1.0)) // no branch 00238 ); 00239 \endcode 00240 00241 You can use the <TT>Var()</TT> functor to assign values to a variable 00242 (<TT>=, +=, -=, *=, /=</TT> are suported). For example, the average gray 00243 value of the image is calculated like this: 00244 00245 \code 00246 using namespace vigra::functor; 00247 00248 vigra::FImage src(w,h); 00249 ...// fill src 00250 00251 double sum = 0.0; 00252 00253 inspectImage(srcImageRange(src), Var(sum) += Arg1()); 00254 00255 std::cout << "Average: " << (sum / (w*h)) << std::endl; 00256 \endcode 00257 00258 For use in \ref inspectImage() and its relatives, there is a second 00259 conditional functor <TT>ifThen()</TT> that emulates the <TT>if()</TT> statement 00260 and does not return a value. Using <TT>ifThen()</TT>, we can calculate the size 00261 of an image region: 00262 00263 \code 00264 using namespace vigra::functor; 00265 00266 vigra::IImage label_image(w,h); 00267 ...// mark regions by labels in label_image 00268 00269 int region_label = ...; // the region we want to inspect 00270 int size = 0; 00271 00272 inspectImage(srcImageRange(label_image), 00273 ifThen(Arg1() == Param(region_label), 00274 Var(size) += Param(1))); 00275 00276 std::cout << "Size of region " << region_label << ": " << size << std::endl; 00277 \endcode 00278 00279 Often, we want to execute several commands in one functor. This can be done 00280 by means of the overloaded <TT>operator,()</TT> ("operator comma"). Expressions 00281 seperated by a comma will be executed in succession. We can thus 00282 simultaneously find the size and the average gray value of a region: 00283 00284 \code 00285 using namespace vigra::functor; 00286 00287 vigra::FImage src(w,h); 00288 vigra::IImage label_image(w,h); 00289 ...// segment src and mark regions in label_image 00290 00291 int region_label = ...; // the region we want to inspect 00292 int size = 0; 00293 double sum = 0.0; 00294 00295 inspectTwoImages(srcImageRange(src), srcImage(label_image), 00296 ifThen(Arg2() == Param(region_label), 00297 ( 00298 Var(size) += Param(1), // the comma operator is invoked 00299 Var(sum) += Arg1() 00300 ))); 00301 00302 std::cout << "Region " << region_label << ": size = " << size << 00303 ", average = " << sum / size << std::endl; 00304 \endcode 00305 00306 [Note that the list of comma-separated expressions must be enclosed in parentheses.] 00307 00308 A comma separated list of expressions can also be applied in the context of 00309 \ref transformImage() and its cousins. Here, a general rule of C++ applies: The 00310 return value of a comma expression is the value of its last subexpression. 00311 For example, we can initialize an image so that each pixel contains its 00312 address in scan order: 00313 00314 \code 00315 using namespace vigra::functor; 00316 00317 vigra::IImage img(w,h); 00318 00319 int count = -1; 00320 00321 initImageWithFunctor(destImageRange(img), 00322 ( 00323 Var(count) += Param(1), 00324 Var(count) // this is the result of the comma expression 00325 )); 00326 \endcode 00327 00328 Further information about how this mechanism works can be found in 00329 <a href="documents/FunctorFactory.ps">this paper</a> (sorry, slightly out of date). 00330 */ 00331 00332 #ifndef DOXYGEN 00333 00334 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) 00335 00336 #include <cmath> 00337 #include <vigra/numerictraits.hxx> 00338 #include <vigra/functortraits.hxx> 00339 00340 00341 namespace vigra { 00342 00343 namespace functor { 00344 00345 /************************************************************/ 00346 /* */ 00347 /* unary functor base template */ 00348 /* */ 00349 /************************************************************/ 00350 00351 00352 struct ErrorType; 00353 00354 template <class Operation> 00355 struct ResultTraits0; 00356 00357 template <class Operation, class T1> 00358 struct ResultTraits1 00359 { 00360 typedef T1 Res; 00361 }; 00362 00363 template <class Operation, class T1, class T2> 00364 struct ResultTraits2 00365 { 00366 typedef typename PromoteTraits<T1, T2>::Promote Res; 00367 }; 00368 00369 template <class Operation, class T1, class T2, class T3> 00370 struct ResultTraits3 00371 { 00372 typedef typename PromoteTraits<T1, T2>::Promote P1; 00373 typedef typename PromoteTraits<P1, T3>::Promote Res; 00374 }; 00375 00376 template <class EXPR> 00377 struct UnaryFunctor 00378 { 00379 UnaryFunctor(EXPR const & e) 00380 : expr_(e) 00381 {} 00382 00383 // typename ResultTraits0<EXPR>::Res 00384 typename ResultTraits0<EXPR>::Res 00385 operator()() const 00386 { 00387 return expr_(); 00388 } 00389 00390 template <class T1> 00391 typename ResultTraits1<EXPR, T1>::Res 00392 operator()(T1 const & v) const 00393 { 00394 return expr_(v); 00395 } 00396 00397 template <class T1, class T2> 00398 typename ResultTraits2<EXPR, T1, T2>::Res 00399 operator()(T1 const & v1, T2 const & v2) const 00400 { 00401 return expr_(v1, v2); 00402 } 00403 00404 template <class T1, class T2, class T3> 00405 typename ResultTraits3<EXPR, T1, T2, T3>::Res 00406 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00407 { 00408 return expr_(v1, v2, v3); 00409 } 00410 00411 protected: 00412 EXPR expr_; 00413 }; 00414 00415 template <class Expr> 00416 struct ResultTraits0<UnaryFunctor<Expr> > 00417 { 00418 typedef typename ResultTraits0<Expr>::Res Res; 00419 }; 00420 00421 template <class Expr, class T1> 00422 struct ResultTraits1<UnaryFunctor<Expr>, T1> 00423 { 00424 typedef typename ResultTraits1<Expr, T1>::Res Res; 00425 }; 00426 00427 template <class Expr, class T1, class T2> 00428 struct ResultTraits2<UnaryFunctor<Expr>, T1, T2> 00429 { 00430 typedef typename ResultTraits2<Expr, T1, T2>::Res Res; 00431 }; 00432 00433 template <class Expr, class T1, class T2, class T3> 00434 struct ResultTraits3<UnaryFunctor<Expr>, T1, T2, T3> 00435 { 00436 typedef typename ResultTraits3<Expr, T1, T2, T3>::Res Res; 00437 }; 00438 00439 /************************************************************/ 00440 /* */ 00441 /* unary functors for arguments */ 00442 /* */ 00443 /************************************************************/ 00444 00445 struct ArgumentFunctor1; 00446 struct ArgumentFunctor2; 00447 struct ArgumentFunctor3; 00448 00449 template <> 00450 struct UnaryFunctor<ArgumentFunctor1> 00451 { 00452 UnaryFunctor() 00453 {} 00454 00455 template <class T1> 00456 T1 const & operator()(T1 const & v1) const 00457 { 00458 return v1; 00459 } 00460 00461 template <class T1, class T2> 00462 T1 const & operator()(T1 const & v1, T2 const &) const 00463 { 00464 return v1; 00465 } 00466 00467 template <class T1, class T2, class T3> 00468 T1 const & operator()(T1 const & v1, T2 const &, T3 const &) const 00469 { 00470 return v1; 00471 } 00472 }; 00473 00474 template <> 00475 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> > 00476 { 00477 typedef ErrorType Res; 00478 }; 00479 00480 template <class T1> 00481 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1> 00482 { 00483 typedef T1 Res; 00484 }; 00485 00486 template <class T1, class T2> 00487 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2> 00488 { 00489 typedef T1 Res; 00490 }; 00491 00492 template <class T1, class T2, class T3> 00493 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3> 00494 { 00495 typedef T1 Res; 00496 }; 00497 00498 /************************************************************/ 00499 00500 inline 00501 UnaryFunctor<ArgumentFunctor1> 00502 Arg1() 00503 { 00504 return UnaryFunctor<ArgumentFunctor1>(); 00505 } 00506 00507 /************************************************************/ 00508 00509 template <> 00510 struct UnaryFunctor<ArgumentFunctor2> 00511 { 00512 UnaryFunctor() 00513 {} 00514 00515 template <class T1, class T2> 00516 T2 const & operator()(T1 const &, T2 const & v2) const 00517 { 00518 return v2; 00519 } 00520 00521 template <class T1, class T2, class T3> 00522 T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const 00523 { 00524 return v2; 00525 } 00526 }; 00527 00528 template <> 00529 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> > 00530 { 00531 typedef ErrorType Res; 00532 }; 00533 00534 template <class T1> 00535 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1> 00536 { 00537 typedef ErrorType Res; 00538 }; 00539 00540 template <class T1, class T2> 00541 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2> 00542 { 00543 typedef T2 Res; 00544 }; 00545 00546 template <class T1, class T2, class T3> 00547 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3> 00548 { 00549 typedef T2 Res; 00550 }; 00551 00552 /************************************************************/ 00553 00554 inline 00555 UnaryFunctor<ArgumentFunctor2> 00556 Arg2() 00557 { 00558 return UnaryFunctor<ArgumentFunctor2>(); 00559 } 00560 00561 /************************************************************/ 00562 00563 template <> 00564 struct UnaryFunctor<ArgumentFunctor3> 00565 { 00566 UnaryFunctor() 00567 {} 00568 00569 template <class T1, class T2, class T3> 00570 T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const 00571 { 00572 return v3; 00573 } 00574 }; 00575 00576 template <> 00577 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> > 00578 { 00579 typedef ErrorType Res; 00580 }; 00581 00582 template <class T1> 00583 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1> 00584 { 00585 typedef ErrorType Res; 00586 }; 00587 00588 template <class T1, class T2> 00589 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2> 00590 { 00591 typedef ErrorType Res; 00592 }; 00593 00594 template <class T1, class T2, class T3> 00595 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3> 00596 { 00597 typedef T3 Res; 00598 }; 00599 00600 /************************************************************/ 00601 00602 inline 00603 UnaryFunctor<ArgumentFunctor3> 00604 Arg3() 00605 { 00606 return UnaryFunctor<ArgumentFunctor3>(); 00607 } 00608 00609 /************************************************************/ 00610 /* */ 00611 /* constant parameters */ 00612 /* */ 00613 /************************************************************/ 00614 00615 template <class T> 00616 struct ParameterFunctor 00617 { 00618 ParameterFunctor(T v) 00619 : value_(v) 00620 {} 00621 00622 T const & operator()() const 00623 { 00624 return value_; 00625 } 00626 00627 template <class U1> 00628 T const & operator()(U1 const &) const 00629 { 00630 return value_; 00631 } 00632 00633 template <class U1, class U2> 00634 T const & operator()(U1 const &, U2 const &) const 00635 { 00636 return value_; 00637 } 00638 00639 template <class U1, class U2, class U3> 00640 T const & operator()(U1 const &, U2 const &, U3 const &) const 00641 { 00642 return value_; 00643 } 00644 00645 protected: 00646 T value_; 00647 }; 00648 00649 template <class T> 00650 struct ResultTraits0<ParameterFunctor<T> > 00651 { 00652 typedef T Res; 00653 }; 00654 00655 template <class T, class T1> 00656 struct ResultTraits1<ParameterFunctor<T>, T1> 00657 { 00658 typedef T Res; 00659 }; 00660 00661 template <class T, class T1, class T2> 00662 struct ResultTraits2<ParameterFunctor<T>, T1, T2> 00663 { 00664 typedef T Res; 00665 }; 00666 00667 template <class T, class T1, class T2, class T3> 00668 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3> 00669 { 00670 typedef T Res; 00671 }; 00672 00673 template <class T> 00674 UnaryFunctor<ParameterFunctor<T> > 00675 Param(T const & v) 00676 { 00677 ParameterFunctor<T> fv(v); 00678 return UnaryFunctor<ParameterFunctor<T> >(fv); 00679 } 00680 00681 /************************************************************/ 00682 /* */ 00683 /* unary analyser base template */ 00684 /* */ 00685 /************************************************************/ 00686 00687 00688 template <class EXPR> 00689 class UnaryAnalyser 00690 { 00691 public: 00692 UnaryAnalyser(EXPR const & e) 00693 : expr_(e) 00694 {} 00695 00696 void operator()() const 00697 { 00698 expr_(); 00699 } 00700 00701 template <class T1> 00702 void operator()(T1 const & v) const 00703 { 00704 expr_(v); 00705 } 00706 00707 template <class T1, class T2> 00708 void operator()(T1 const & v1, T2 const & v2) const 00709 { 00710 expr_(v1, v2); 00711 } 00712 00713 template <class T1, class T2, class T3> 00714 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00715 { 00716 expr_(v1, v2, v3); 00717 } 00718 protected: 00719 00720 EXPR expr_; 00721 }; 00722 00723 /************************************************************/ 00724 /* */ 00725 /* variable assignment */ 00726 /* */ 00727 /************************************************************/ 00728 00729 template <class T> 00730 struct VarFunctor; 00731 00732 template <class T> 00733 struct UnaryFunctor<VarFunctor<T> >; 00734 00735 /************************************************************/ 00736 00737 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \ 00738 template <class V, class EXPR> \ 00739 struct AssignmentFunctor_##name \ 00740 { \ 00741 AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v, \ 00742 UnaryFunctor<EXPR> const & e) \ 00743 : value_(v.value_), expr_(e) \ 00744 {} \ 00745 \ 00746 V & operator()() const \ 00747 { \ 00748 const_cast<V &>(value_) op expr_(); \ 00749 return const_cast<V &>(value_); \ 00750 } \ 00751 \ 00752 template <class T1> \ 00753 V & operator()(T1 const & v1) const \ 00754 { \ 00755 const_cast<V &>(value_) op expr_(v1); \ 00756 return const_cast<V &>(value_); \ 00757 } \ 00758 \ 00759 template <class T1, class T2> \ 00760 V & operator()(T1 const & v1, T2 const & v2) const \ 00761 { \ 00762 const_cast<V &>(value_) op expr_(v1, v2); \ 00763 return const_cast<V &>(value_); \ 00764 } \ 00765 \ 00766 template <class T1, class T2, class T3> \ 00767 V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 00768 { \ 00769 const_cast<V &>(value_) op expr_(v1, v2, v3); \ 00770 return const_cast<V &>(value_); \ 00771 } \ 00772 \ 00773 private: \ 00774 V & value_; \ 00775 UnaryFunctor<EXPR> expr_; \ 00776 }; 00777 00778 /************************************************************/ 00779 00780 MAKE_ASSIGNMENT_FUNCTOR(assign, =) 00781 MAKE_ASSIGNMENT_FUNCTOR(add, +=) 00782 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=) 00783 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=) 00784 MAKE_ASSIGNMENT_FUNCTOR(divide, /=) 00785 00786 #undef MAKE_ASSIGNMENT_FUNCTOR 00787 00788 /************************************************************/ 00789 /* */ 00790 /* variables */ 00791 /* */ 00792 /************************************************************/ 00793 00794 template <class T> 00795 struct UnaryFunctor<VarFunctor<T> > 00796 { 00797 typedef T Res; 00798 00799 UnaryFunctor(T & v) 00800 : value_(v) 00801 {} 00802 00803 template <class EXPR> 00804 UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > > 00805 operator=(UnaryFunctor<EXPR> const & e) 00806 { 00807 AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e); 00808 return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va); 00809 } 00810 00811 template <class EXPR> 00812 UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > > 00813 operator+=(UnaryFunctor<EXPR> const & e) 00814 { 00815 AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e); 00816 return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va); 00817 } 00818 00819 template <class EXPR> 00820 UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > > 00821 operator-=(UnaryFunctor<EXPR> const & e) 00822 { 00823 AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e); 00824 return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va); 00825 } 00826 00827 template <class EXPR> 00828 UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > > 00829 operator*=(UnaryFunctor<EXPR> const & e) 00830 { 00831 AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e); 00832 return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va); 00833 } 00834 00835 template <class EXPR> 00836 UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > > 00837 operator/=(UnaryFunctor<EXPR> const & e) 00838 { 00839 AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e); 00840 return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va); 00841 } 00842 00843 T const & operator()() const 00844 { 00845 return value_; 00846 } 00847 00848 template <class U1> 00849 T const & operator()(U1 const &) const 00850 { 00851 return value_; 00852 } 00853 00854 template <class U1, class U2> 00855 T const & operator()(U1 const &, U2 const &) const 00856 { 00857 return value_; 00858 } 00859 00860 template <class U1, class U2, class U3> 00861 T const & operator()(U1 const &, U2 const &, U3 const &) const 00862 { 00863 return value_; 00864 } 00865 00866 T & value_; 00867 }; 00868 00869 template <class T> 00870 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > > 00871 { 00872 typedef T Res; 00873 }; 00874 00875 template <class T, class T1> 00876 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1> 00877 { 00878 typedef T Res; 00879 }; 00880 00881 template <class T, class T1, class T2> 00882 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2> 00883 { 00884 typedef T Res; 00885 }; 00886 00887 template <class T, class T1, class T2, class T3> 00888 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3> 00889 { 00890 typedef T Res; 00891 }; 00892 00893 template <class T> 00894 UnaryFunctor<VarFunctor<T> > 00895 Var(T & v) 00896 { 00897 return UnaryFunctor<VarFunctor<T> >(v); 00898 } 00899 00900 /************************************************************/ 00901 /* */ 00902 /* if then */ 00903 /* */ 00904 /************************************************************/ 00905 00906 template <class EXPR1, class EXPR2> 00907 struct IfThenFunctor 00908 { 00909 typedef void Res; 00910 00911 IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2) 00912 : expr1_(e1), expr2_(e2) 00913 {} 00914 00915 void operator()() const 00916 { 00917 if( expr1_() ) expr2_(); 00918 } 00919 00920 template <class T> 00921 void operator()(T const & v1) const 00922 { 00923 if( expr1_(v1) ) expr2_(v1); 00924 } 00925 00926 template <class T1, class T2> 00927 void operator()(T1 const & v1, T2 const & v2) const 00928 { 00929 if( expr1_(v1, v2) ) expr2_(v1, v2); 00930 } 00931 00932 template <class T1, class T2, class T3> 00933 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00934 { 00935 if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3); 00936 } 00937 00938 private: 00939 00940 EXPR1 expr1_; 00941 EXPR2 expr2_; 00942 }; 00943 00944 template <class EXPR1, class EXPR2> 00945 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00946 UnaryAnalyser<EXPR2> > > 00947 ifThen(UnaryFunctor<EXPR1> const & e1, 00948 UnaryAnalyser<EXPR2> const & e2) 00949 { 00950 IfThenFunctor<UnaryFunctor<EXPR1>, 00951 UnaryAnalyser<EXPR2> > p(e1, e2); 00952 return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00953 UnaryAnalyser<EXPR2> > >(p); 00954 } 00955 00956 /************************************************************/ 00957 /* */ 00958 /* if then else */ 00959 /* */ 00960 /************************************************************/ 00961 00962 template <class EXPR1, class EXPR2, class EXPR3> 00963 struct IfThenElseFunctor; 00964 00965 template <class EXPR1, class EXPR2, class EXPR3> 00966 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> > 00967 { 00968 typedef typename ResultTraits0<EXPR2>::Res R2; 00969 typedef typename ResultTraits0<EXPR3>::Res R3; 00970 typedef typename PromoteTraits<R2, R3>::Promote Res; 00971 }; 00972 00973 template <class EXPR1, class EXPR2, class EXPR3, class T1> 00974 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1> 00975 { 00976 typedef typename ResultTraits1<EXPR2, T1>::Res R2; 00977 typedef typename ResultTraits1<EXPR3, T1>::Res R3; 00978 typedef typename PromoteTraits<R2, R3>::Promote Res; 00979 }; 00980 00981 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2> 00982 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2> 00983 { 00984 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; 00985 typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3; 00986 typedef typename PromoteTraits<R2, R3>::Promote Res; 00987 }; 00988 00989 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3> 00990 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3> 00991 { 00992 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; 00993 typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3; 00994 typedef typename PromoteTraits<R2, R3>::Promote Res; 00995 }; 00996 00997 template <class EXPR1, class EXPR2, class EXPR3> 00998 struct IfThenElseFunctor 00999 { 01000 IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3) 01001 : expr1_(e1), expr2_(e2), expr3_(e3) 01002 {} 01003 01004 typename ResultTraits0<IfThenElseFunctor>::Res 01005 operator()() const 01006 { 01007 typename 01008 ResultTraits0<IfThenElseFunctor>::Res 01009 r2(expr2_()); 01010 typename 01011 ResultTraits0<IfThenElseFunctor>::Res 01012 r3(expr3_()); 01013 return expr1_() ? r2 : r3; 01014 } 01015 01016 template <class T> 01017 typename ResultTraits1<IfThenElseFunctor, T>::Res 01018 operator()(T const & v1) const 01019 { 01020 typename 01021 ResultTraits1<IfThenElseFunctor, T>::Res 01022 r2(expr2_(v1)); 01023 typename 01024 ResultTraits1<IfThenElseFunctor, T>::Res 01025 r3(expr3_(v1)); 01026 return expr1_(v1) ? r2 : r3; 01027 } 01028 01029 template <class T1, class T2> 01030 typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01031 operator()(T1 const & v1, T2 const & v2) const 01032 { 01033 typename 01034 ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01035 r2(expr2_(v1, v2)); 01036 typename 01037 ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01038 r3(expr3_(v1, v2)); 01039 return expr1_(v1, v2) ? r2 : r3; 01040 } 01041 01042 template <class T1, class T2, class T3> 01043 typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01044 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01045 { 01046 typename 01047 ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01048 r2(expr2_(v1, v2, v3)); 01049 typename 01050 ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01051 r3(expr3_(v1, v2, v3)); 01052 return expr1_(v1, v2, v3) ? r2 : r3; 01053 } 01054 01055 private: 01056 01057 EXPR1 expr1_; 01058 EXPR2 expr2_; 01059 EXPR3 expr3_; 01060 }; 01061 01062 template <class EXPR1, class EXPR2, class EXPR3> 01063 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01064 UnaryFunctor<EXPR2>, 01065 UnaryFunctor<EXPR3> > > 01066 ifThenElse(UnaryFunctor<EXPR1> const & e1, 01067 UnaryFunctor<EXPR2> const & e2, 01068 UnaryFunctor<EXPR3> const & e3) 01069 { 01070 IfThenElseFunctor<UnaryFunctor<EXPR1>, 01071 UnaryFunctor<EXPR2>, 01072 UnaryFunctor<EXPR3> > p(e1, e2, e3); 01073 return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01074 UnaryFunctor<EXPR2>, 01075 UnaryFunctor<EXPR3> > >(p); 01076 } 01077 01078 /************************************************************/ 01079 /* */ 01080 /* functors for unary functions */ 01081 /* */ 01082 /************************************************************/ 01083 01084 #define MAKE_FUNCTOR_UNARY_FUNCTION(function) \ 01085 using std::function; \ 01086 template <class EXPR> \ 01087 struct Functor_##function; \ 01088 \ 01089 template <class EXPR> \ 01090 struct ResultTraits0<Functor_##function<EXPR> > \ 01091 { \ 01092 typedef typename ResultTraits0<EXPR>::Res R1; \ 01093 typedef typename NumericTraits<R1>::RealPromote Res; \ 01094 }; \ 01095 \ 01096 template <class EXPR, class T1> \ 01097 struct ResultTraits1<Functor_##function<EXPR>, T1> \ 01098 { \ 01099 typedef typename ResultTraits1<EXPR, T1>::Res R1; \ 01100 typedef typename NumericTraits<R1>::RealPromote Res; \ 01101 }; \ 01102 \ 01103 template <class EXPR, class T1, class T2> \ 01104 struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \ 01105 { \ 01106 typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \ 01107 typedef typename NumericTraits<R1>::RealPromote Res; \ 01108 }; \ 01109 \ 01110 template <class EXPR, class T1, class T2, class T3> \ 01111 struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \ 01112 { \ 01113 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \ 01114 typedef typename NumericTraits<R1>::RealPromote Res; \ 01115 }; \ 01116 \ 01117 template <class EXPR> \ 01118 struct Functor_##function \ 01119 { \ 01120 Functor_##function(EXPR const & e) \ 01121 : expr_(e) \ 01122 {} \ 01123 \ 01124 typename ResultTraits0<Functor_##function>::Res \ 01125 operator()() const \ 01126 { \ 01127 return function(expr_()); \ 01128 } \ 01129 \ 01130 template <class T> \ 01131 typename ResultTraits1<Functor_##function, T>::Res \ 01132 operator()(T const & v1) const \ 01133 { \ 01134 return function(expr_(v1)); \ 01135 } \ 01136 \ 01137 template <class T1, class T2> \ 01138 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01139 operator()(T1 const & v1, T2 const & v2) const \ 01140 { \ 01141 return function(expr_(v1, v2)); \ 01142 } \ 01143 \ 01144 template <class T1, class T2, class T3> \ 01145 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01146 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01147 { \ 01148 return function(expr_(v1, v2, v3)); \ 01149 } \ 01150 \ 01151 protected: \ 01152 \ 01153 EXPR expr_; \ 01154 }; \ 01155 \ 01156 template <class EXPR> \ 01157 UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \ 01158 function(UnaryFunctor<EXPR> const & e) \ 01159 { \ 01160 Functor_##function<UnaryFunctor<EXPR> > p(e); \ 01161 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \ 01162 } 01163 01164 /************************************************************/ 01165 01166 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt) 01167 MAKE_FUNCTOR_UNARY_FUNCTION(exp) 01168 MAKE_FUNCTOR_UNARY_FUNCTION(log) 01169 MAKE_FUNCTOR_UNARY_FUNCTION(log10) 01170 MAKE_FUNCTOR_UNARY_FUNCTION(sin) 01171 MAKE_FUNCTOR_UNARY_FUNCTION(asin) 01172 MAKE_FUNCTOR_UNARY_FUNCTION(cos) 01173 MAKE_FUNCTOR_UNARY_FUNCTION(acos) 01174 MAKE_FUNCTOR_UNARY_FUNCTION(tan) 01175 MAKE_FUNCTOR_UNARY_FUNCTION(atan) 01176 MAKE_FUNCTOR_UNARY_FUNCTION(abs) 01177 MAKE_FUNCTOR_UNARY_FUNCTION(floor) 01178 MAKE_FUNCTOR_UNARY_FUNCTION(ceil) 01179 01180 #undef MAKE_FUNCTOR_UNARY_FUNCTION 01181 01182 /************************************************************/ 01183 /* */ 01184 /* functors for unary operators */ 01185 /* */ 01186 /************************************************************/ 01187 01188 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \ 01189 template <class EXPR> \ 01190 struct Functor_##name; \ 01191 \ 01192 template <class EXPR> \ 01193 struct ResultTraits0<Functor_##name<EXPR> > \ 01194 { \ 01195 typedef typename ResultTraits0<EXPR>::Res Res; \ 01196 }; \ 01197 \ 01198 template <class EXPR, class T1> \ 01199 struct ResultTraits1<Functor_##name<EXPR>, T1> \ 01200 { \ 01201 typedef typename ResultTraits1<EXPR, T1>::Res Res; \ 01202 }; \ 01203 \ 01204 template <class EXPR, class T1, class T2> \ 01205 struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \ 01206 { \ 01207 typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \ 01208 }; \ 01209 \ 01210 template <class EXPR, class T1, class T2, class T3> \ 01211 struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \ 01212 { \ 01213 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \ 01214 }; \ 01215 \ 01216 template <class EXPR> \ 01217 struct Functor_##name \ 01218 { \ 01219 Functor_##name(EXPR const & e) \ 01220 : expr_(e) \ 01221 {} \ 01222 \ 01223 typename ResultTraits0<Functor_##name>::Res \ 01224 operator()() const \ 01225 { \ 01226 return op expr_(); \ 01227 } \ 01228 \ 01229 template <class T> \ 01230 typename ResultTraits1<Functor_##name, T>::Res \ 01231 operator()(T const & v1) const \ 01232 { \ 01233 return op expr_(v1); \ 01234 } \ 01235 \ 01236 template <class T1, class T2> \ 01237 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01238 operator()(T1 const & v1, T2 const & v2) const \ 01239 { \ 01240 return op expr_(v1, v2); \ 01241 } \ 01242 \ 01243 template <class T1, class T2, class T3> \ 01244 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01245 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01246 { \ 01247 return op expr_(v1, v2, v3); \ 01248 } \ 01249 protected: \ 01250 \ 01251 EXPR expr_; \ 01252 }; \ 01253 \ 01254 template <class EXPR> \ 01255 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \ 01256 operator op(UnaryFunctor<EXPR> const & e) \ 01257 { \ 01258 Functor_##name<UnaryFunctor<EXPR> > p(e); \ 01259 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \ 01260 } 01261 01262 01263 /************************************************************/ 01264 01265 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -) 01266 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !) 01267 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~) 01268 01269 #undef MAKE_FUNCTOR_UNARY_OPERATOR 01270 01271 /************************************************************/ 01272 /* */ 01273 /* functors for binary functions */ 01274 /* */ 01275 /************************************************************/ 01276 01277 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \ 01278 using std::function; \ 01279 template <class EXPR1, class EXPR2> \ 01280 struct Functor_##function; \ 01281 \ 01282 template <class EXPR1, class EXPR2> \ 01283 struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \ 01284 { \ 01285 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01286 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01287 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01288 typedef typename NumericTraits<R3>::RealPromote Res; \ 01289 }; \ 01290 \ 01291 template <class EXPR1, class EXPR2, class T1> \ 01292 struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \ 01293 { \ 01294 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01295 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01296 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01297 typedef typename NumericTraits<R3>::RealPromote Res; \ 01298 }; \ 01299 \ 01300 template <class EXPR1, class EXPR2, class T1, class T2> \ 01301 struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \ 01302 { \ 01303 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01304 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01305 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01306 typedef typename NumericTraits<R3>::RealPromote Res; \ 01307 }; \ 01308 \ 01309 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01310 struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \ 01311 { \ 01312 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01313 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01314 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01315 typedef typename NumericTraits<R3>::RealPromote Res; \ 01316 }; \ 01317 \ 01318 template <class EXPR1, class EXPR2> \ 01319 struct Functor_##function \ 01320 { \ 01321 Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \ 01322 : expr1_(e1), expr2_(e2) \ 01323 {} \ 01324 \ 01325 typename ResultTraits0<Functor_##function>::Res \ 01326 operator()() const \ 01327 { \ 01328 return function(expr1_(), expr2_()); \ 01329 } \ 01330 \ 01331 template <class T> \ 01332 typename ResultTraits1<Functor_##function, T>::Res \ 01333 operator()(T const & v1) const \ 01334 { \ 01335 return function(expr1_(v1), expr2_(v1)); \ 01336 } \ 01337 \ 01338 template <class T1, class T2> \ 01339 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01340 operator()(T1 const & v1, T2 const & v2) const \ 01341 { \ 01342 return function(expr1_(v1, v2), expr2_(v1, v2)); \ 01343 } \ 01344 \ 01345 template <class T1, class T2, class T3> \ 01346 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01347 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01348 { \ 01349 return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \ 01350 } \ 01351 \ 01352 private: \ 01353 \ 01354 EXPR1 expr1_; \ 01355 EXPR2 expr2_; \ 01356 }; \ 01357 \ 01358 template <class EXPR1, class EXPR2> \ 01359 UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01360 function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01361 { \ 01362 Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01363 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, \ 01364 UnaryFunctor<EXPR2> > >(p); \ 01365 } 01366 01367 /************************************************************/ 01368 01369 MAKE_FUNCTOR_BINARY_FUNCTION(pow) 01370 MAKE_FUNCTOR_BINARY_FUNCTION(atan2) 01371 MAKE_FUNCTOR_BINARY_FUNCTION(fmod) 01372 01373 #undef MAKE_FUNCTOR_BINARY_FUNCTION 01374 01375 /************************************************************/ 01376 01377 #define MAKE_FUNCTOR_MINMAX(name, op) \ 01378 template <class EXPR1, class EXPR2> \ 01379 struct Functor_##name; \ 01380 \ 01381 template <class EXPR1, class EXPR2> \ 01382 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01383 { \ 01384 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01385 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01386 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01387 }; \ 01388 \ 01389 template <class EXPR1, class EXPR2, class T1> \ 01390 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01391 { \ 01392 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01393 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01394 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01395 }; \ 01396 \ 01397 template <class EXPR1, class EXPR2, class T1, class T2> \ 01398 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01399 { \ 01400 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01401 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01402 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01403 }; \ 01404 \ 01405 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01406 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01407 { \ 01408 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01409 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01410 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01411 }; \ 01412 \ 01413 template <class EXPR1, class EXPR2> \ 01414 struct Functor_##name \ 01415 { \ 01416 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01417 : expr1_(e1), expr2_(e2) \ 01418 {} \ 01419 \ 01420 typename ResultTraits0<Functor_##name>::Res \ 01421 operator()() const \ 01422 { \ 01423 typename \ 01424 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \ 01425 typename \ 01426 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \ 01427 return (r1 op r2) ? r1 : r2; \ 01428 } \ 01429 \ 01430 template <class T> \ 01431 typename ResultTraits1<Functor_##name, T>::Res \ 01432 operator()(T const & v1) const \ 01433 { \ 01434 typename \ 01435 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \ 01436 typename \ 01437 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \ 01438 return (r1 op r2) ? r1 : r2; \ 01439 } \ 01440 \ 01441 template <class T1, class T2> \ 01442 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01443 operator()(T1 const & v1, T2 const & v2) const \ 01444 { \ 01445 typename \ 01446 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \ 01447 typename \ 01448 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \ 01449 return (r1 op r2) ? r1 : r2; \ 01450 } \ 01451 \ 01452 template <class T1, class T2, class T3> \ 01453 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01454 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01455 { \ 01456 typename \ 01457 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \ 01458 typename \ 01459 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \ 01460 return (r1 op r2) ? r1 : r2; \ 01461 } \ 01462 \ 01463 private: \ 01464 \ 01465 EXPR1 expr1_; \ 01466 EXPR2 expr2_; \ 01467 }; \ 01468 \ 01469 template <class EXPR1, class EXPR2> \ 01470 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01471 name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01472 { \ 01473 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01474 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01475 UnaryFunctor<EXPR2> > >(p); \ 01476 } 01477 01478 MAKE_FUNCTOR_MINMAX(min, <) 01479 MAKE_FUNCTOR_MINMAX(max, >) 01480 01481 #undef MAKE_FUNCTOR_MINMAX 01482 01483 /************************************************************/ 01484 /* */ 01485 /* functors for binary operators */ 01486 /* */ 01487 /************************************************************/ 01488 01489 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \ 01490 template <class EXPR1, class EXPR2> \ 01491 struct Functor_##name; \ 01492 \ 01493 template <class EXPR1, class EXPR2> \ 01494 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01495 { \ 01496 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01497 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01498 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01499 }; \ 01500 \ 01501 template <class EXPR1, class EXPR2, class T1> \ 01502 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01503 { \ 01504 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01505 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01506 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01507 }; \ 01508 \ 01509 template <class EXPR1, class EXPR2, class T1, class T2> \ 01510 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01511 { \ 01512 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01513 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01514 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01515 }; \ 01516 \ 01517 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01518 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01519 { \ 01520 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01521 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01522 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01523 }; \ 01524 \ 01525 template <class EXPR1, class EXPR2> \ 01526 struct Functor_##name \ 01527 { \ 01528 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01529 : expr1_(e1), expr2_(e2) \ 01530 {} \ 01531 \ 01532 typename ResultTraits0<Functor_##name>::Res \ 01533 operator()() const \ 01534 { \ 01535 return expr1_() op expr2_(); \ 01536 } \ 01537 \ 01538 template <class T> \ 01539 typename ResultTraits1<Functor_##name, T>::Res \ 01540 operator()(T const & v1) const \ 01541 { \ 01542 return expr1_(v1) op expr2_(v1); \ 01543 } \ 01544 \ 01545 template <class T1, class T2> \ 01546 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01547 operator()(T1 const & v1, T2 const & v2) const \ 01548 { \ 01549 return expr1_(v1, v2) op expr2_(v1, v2); \ 01550 } \ 01551 \ 01552 template <class T1, class T2, class T3> \ 01553 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01554 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01555 { \ 01556 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01557 } \ 01558 \ 01559 private: \ 01560 \ 01561 EXPR1 expr1_; \ 01562 EXPR2 expr2_; \ 01563 }; \ 01564 \ 01565 template <class EXPR1, class EXPR2> \ 01566 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01567 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01568 { \ 01569 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01570 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01571 UnaryFunctor<EXPR2> > >(p); \ 01572 } 01573 01574 /************************************************************/ 01575 01576 MAKE_FUNCTOR_BINARY_OPERATOR(add, +) 01577 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -) 01578 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *) 01579 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /) 01580 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %) 01581 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &) 01582 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |) 01583 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^) 01584 01585 #undef MAKE_FUNCTOR_BINARY_OPERATOR 01586 01587 /************************************************************/ 01588 01589 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \ 01590 template <class EXPR1, class EXPR2> \ 01591 struct Functor_##name; \ 01592 \ 01593 template <class EXPR1, class EXPR2> \ 01594 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01595 { \ 01596 typedef bool Res; \ 01597 }; \ 01598 \ 01599 template <class EXPR1, class EXPR2, class T1> \ 01600 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01601 { \ 01602 typedef bool Res; \ 01603 }; \ 01604 \ 01605 template <class EXPR1, class EXPR2, class T1, class T2> \ 01606 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01607 { \ 01608 typedef bool Res; \ 01609 }; \ 01610 \ 01611 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01612 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01613 { \ 01614 typedef bool Res; \ 01615 }; \ 01616 \ 01617 template <class EXPR1, class EXPR2> \ 01618 struct Functor_##name \ 01619 { \ 01620 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01621 : expr1_(e1), expr2_(e2) \ 01622 {} \ 01623 \ 01624 bool operator()() const \ 01625 { \ 01626 return expr1_() op expr2_(); \ 01627 } \ 01628 \ 01629 template <class T> \ 01630 bool operator()(T const & v1) const \ 01631 { \ 01632 return expr1_(v1) op expr2_(v1); \ 01633 } \ 01634 \ 01635 template <class T1, class T2> \ 01636 bool operator()(T1 const & v1, T2 const & v2) const \ 01637 { \ 01638 return expr1_(v1, v2) op expr2_(v1, v2); \ 01639 } \ 01640 \ 01641 template <class T1, class T2, class T3> \ 01642 bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01643 { \ 01644 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01645 } \ 01646 \ 01647 private: \ 01648 \ 01649 EXPR1 expr1_; \ 01650 EXPR2 expr2_; \ 01651 }; \ 01652 \ 01653 template <class EXPR1, class EXPR2> \ 01654 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01655 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01656 { \ 01657 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01658 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01659 UnaryFunctor<EXPR2> > >(p); \ 01660 } 01661 01662 /************************************************************/ 01663 01664 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==) 01665 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=) 01666 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <) 01667 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=) 01668 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >) 01669 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=) 01670 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&) 01671 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||) 01672 01673 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL 01674 01675 /************************************************************/ 01676 /* */ 01677 /* unary apply */ 01678 /* */ 01679 /************************************************************/ 01680 01681 template <class EXPR, class RES, class ARG> 01682 struct UnaryFctPtrFunctor 01683 { 01684 UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG)) 01685 : expr_(e), f_(fct) 01686 {} 01687 01688 RES operator()() const 01689 { 01690 return f_(expr_()); 01691 } 01692 01693 template <class T> 01694 RES operator()(T const & v1) const 01695 { 01696 return f_(expr_(v1)); 01697 } 01698 01699 template <class T1, class T2> 01700 RES operator()(T1 const & v1, T2 const & v2) const 01701 { 01702 return f_(expr_(v1, v2)); 01703 } 01704 01705 template <class T1, class T2, class T3> 01706 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01707 { 01708 return f_(expr_(v1, v2, v3)); 01709 } 01710 protected: 01711 01712 EXPR expr_; 01713 RES (*f_)(ARG); 01714 }; 01715 01716 template <class EXPR, class RES, class ARG> 01717 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> > 01718 { 01719 typedef RES Res; 01720 }; 01721 01722 template <class EXPR, class RES, class ARG, class T1> 01723 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1> 01724 { 01725 typedef RES Res; 01726 }; 01727 01728 template <class EXPR, class RES, class ARG, class T1, class T2> 01729 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2> 01730 { 01731 typedef RES Res; 01732 }; 01733 01734 template <class EXPR, class RES, class ARG, class T1, class T2, class T3> 01735 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3> 01736 { 01737 typedef RES Res; 01738 }; 01739 01740 template <class EXPR, class RES, class ARG> 01741 UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> > 01742 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e) 01743 { 01744 UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f); 01745 return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p); 01746 } 01747 01748 /************************************************************/ 01749 /* */ 01750 /* binary apply */ 01751 /* */ 01752 /************************************************************/ 01753 01754 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01755 struct BinaryFctPtrFunctor 01756 { 01757 BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2, 01758 RES (*f)(ARG1, ARG2)) 01759 : expr1_(e1), expr2_(e2), f_(f) 01760 {} 01761 01762 RES operator()() const 01763 { 01764 return f_(expr1_(), expr2_()); 01765 } 01766 01767 template <class T> 01768 RES operator()(T const & v1) const 01769 { 01770 return f_(expr1_(v1), expr2_(v1)); 01771 } 01772 01773 template <class T1, class T2> 01774 RES operator()(T1 const & v1, T2 const & v2) const 01775 { 01776 return f_(expr1_(v1, v2), expr2_(v1, v2)); 01777 } 01778 01779 template <class T1, class T2, class T3> 01780 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01781 { 01782 return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); 01783 } 01784 protected: 01785 01786 EXPR1 expr1_; 01787 EXPR2 expr2_; 01788 RES (*f_)(ARG1, ARG2); 01789 }; 01790 01791 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01792 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> > 01793 { 01794 typedef RES Res; 01795 }; 01796 01797 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01798 class T1> 01799 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1> 01800 { 01801 typedef RES Res; 01802 }; 01803 01804 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01805 class T1, class T2> 01806 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2> 01807 { 01808 typedef RES Res; 01809 }; 01810 01811 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01812 class T1, class T2, class T3> 01813 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3> 01814 { 01815 typedef RES Res; 01816 }; 01817 01818 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01819 UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01820 UnaryFunctor<EXPR2>, 01821 RES, ARG1, ARG2> > 01822 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1, 01823 UnaryFunctor<EXPR2> const & e2) 01824 { 01825 BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01826 UnaryFunctor<EXPR2>, 01827 RES, ARG1, ARG2> p(e1, e2, f); 01828 return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01829 UnaryFunctor<EXPR2>, 01830 RES, ARG1, ARG2> >(p); 01831 } 01832 01833 /************************************************************/ 01834 /* */ 01835 /* comma operator */ 01836 /* */ 01837 /************************************************************/ 01838 01839 template <class EXPR1, class EXPR2> 01840 struct CommaFunctor 01841 { 01842 CommaFunctor(EXPR1 const & e1, EXPR2 const & e2) 01843 : expr1_(e1), expr2_(e2) 01844 {} 01845 01846 typename ResultTraits0<EXPR2>::Res 01847 operator()() const 01848 { 01849 expr1_(); 01850 return expr2_(); 01851 } 01852 01853 template <class T> 01854 typename ResultTraits1<EXPR2, T>::Res 01855 operator()(T const & v1) const 01856 { 01857 expr1_(v1); 01858 return expr2_(v1); 01859 } 01860 01861 template <class T1, class T2> 01862 typename ResultTraits2<EXPR2, T1, T2>::Res 01863 operator()(T1 const & v1, T2 const & v2) const 01864 { 01865 expr1_(v1, v2); 01866 return expr2_(v1, v2); 01867 } 01868 01869 template <class T1, class T2, class T3> 01870 typename ResultTraits3<EXPR2, T1, T2, T3>::Res 01871 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01872 { 01873 expr1_(v1, v2, v3); 01874 return expr2_(v1, v2, v3); 01875 } 01876 01877 protected: 01878 01879 EXPR1 expr1_; 01880 EXPR2 expr2_; 01881 }; 01882 01883 template <class Expr1, class Expr2> 01884 struct ResultTraits0<CommaFunctor<Expr1, Expr2> > 01885 { 01886 typedef typename ResultTraits0<Expr2>::Res Res; 01887 }; 01888 01889 template <class Expr1, class Expr2, class T1> 01890 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1> 01891 { 01892 typedef typename ResultTraits1<Expr2, T1>::Res Res; 01893 }; 01894 01895 template <class Expr1, class Expr2, class T1, class T2> 01896 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2> 01897 { 01898 typedef typename ResultTraits2<Expr2, T1, T2>::Res Res; 01899 }; 01900 01901 template <class Expr1, class Expr2, class T1, class T2, class T3> 01902 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3> 01903 { 01904 typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res; 01905 }; 01906 01907 template <class EXPR1, class EXPR2> 01908 UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01909 UnaryFunctor<EXPR2> > > 01910 operator,(UnaryAnalyser<EXPR1> const & e1, 01911 UnaryFunctor<EXPR2> const & e2) 01912 { 01913 CommaFunctor<UnaryAnalyser<EXPR1>, 01914 UnaryFunctor<EXPR2> > p(e1, e2); 01915 return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01916 UnaryFunctor<EXPR2> > >(p); 01917 } 01918 01919 /************************************************************/ 01920 01921 template <class EXPR1, class EXPR2> 01922 struct CommaAnalyser 01923 { 01924 CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2) 01925 : expr1_(e1), expr2_(e2) 01926 {} 01927 01928 void operator()() const 01929 { 01930 expr1_(); 01931 expr2_(); 01932 } 01933 01934 template <class T> 01935 void operator()(T const & v1) const 01936 { 01937 expr1_(v1); 01938 expr2_(v1); 01939 } 01940 01941 template <class T1, class T2> 01942 void operator()(T1 const & v1, T2 const & v2) const 01943 { 01944 expr1_(v1, v2); 01945 expr2_(v1, v2); 01946 } 01947 01948 template <class T1, class T2, class T3> 01949 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01950 { 01951 expr1_(v1, v2, v3); 01952 expr2_(v1, v2, v3); 01953 } 01954 01955 protected: 01956 01957 EXPR1 expr1_; 01958 EXPR2 expr2_; 01959 }; 01960 01961 template <class EXPR1, class EXPR2> 01962 UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 01963 UnaryAnalyser<EXPR2> > > 01964 operator,(UnaryAnalyser<EXPR1> const & e1, 01965 UnaryAnalyser<EXPR2> const & e2) 01966 { 01967 CommaAnalyser<UnaryAnalyser<EXPR1>, 01968 UnaryAnalyser<EXPR2> > p(e1, e2); 01969 return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 01970 UnaryAnalyser<EXPR2> > >(p); 01971 } 01972 01973 } // namespace functor 01974 01975 template <class T> 01976 class FunctorTraits<functor::UnaryFunctor<T> > 01977 : public FunctorTraitsBase<functor::UnaryFunctor<T> > 01978 { 01979 public: 01980 typedef VigraTrueType isInitializer; 01981 typedef VigraTrueType isUnaryFunctor; 01982 typedef VigraTrueType isBinaryFunctor; 01983 typedef VigraTrueType isTernaryFunctor; 01984 }; 01985 01986 template <class T> 01987 class FunctorTraits<functor::UnaryAnalyser<T> > 01988 : public FunctorTraitsBase<functor::UnaryAnalyser<T> > 01989 { 01990 public: 01991 typedef VigraTrueType isUnaryAnalyser; 01992 typedef VigraTrueType isBinaryAnalyser; 01993 typedef VigraTrueType isTernaryAnalyser; 01994 }; 01995 01996 01997 01998 } // namespace vigra 01999 02000 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */ 02001 02002 #endif // DOXYGEN 02003 02004 #endif /* VIGRA_FUNCTOREXPRESSION_HXX */ 02005 02006
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|