[ 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.5.0, Dec 07 2006 ) */ 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 "numerictraits.hxx" 00338 #include "mathutil.hxx" 00339 #include "functortraits.hxx" 00340 00341 00342 namespace vigra { 00343 00344 namespace functor { 00345 00346 /************************************************************/ 00347 /* */ 00348 /* unary functor base template */ 00349 /* */ 00350 /************************************************************/ 00351 00352 00353 struct ErrorType; 00354 00355 template <class Operation> 00356 struct ResultTraits0; 00357 00358 template <class Operation, class T1> 00359 struct ResultTraits1 00360 { 00361 typedef T1 Res; 00362 }; 00363 00364 template <class Operation, class T1, class T2> 00365 struct ResultTraits2 00366 { 00367 typedef typename PromoteTraits<T1, T2>::Promote Res; 00368 }; 00369 00370 template <class Operation, class T1, class T2, class T3> 00371 struct ResultTraits3 00372 { 00373 typedef typename PromoteTraits<T1, T2>::Promote P1; 00374 typedef typename PromoteTraits<P1, T3>::Promote Res; 00375 }; 00376 00377 template <class EXPR> 00378 struct UnaryFunctor 00379 { 00380 UnaryFunctor(EXPR const & e) 00381 : expr_(e) 00382 {} 00383 00384 // typename ResultTraits0<EXPR>::Res 00385 typename ResultTraits0<EXPR>::Res 00386 operator()() const 00387 { 00388 return expr_(); 00389 } 00390 00391 template <class T1> 00392 typename ResultTraits1<EXPR, T1>::Res 00393 operator()(T1 const & v) const 00394 { 00395 return expr_(v); 00396 } 00397 00398 template <class T1, class T2> 00399 typename ResultTraits2<EXPR, T1, T2>::Res 00400 operator()(T1 const & v1, T2 const & v2) const 00401 { 00402 return expr_(v1, v2); 00403 } 00404 00405 template <class T1, class T2, class T3> 00406 typename ResultTraits3<EXPR, T1, T2, T3>::Res 00407 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00408 { 00409 return expr_(v1, v2, v3); 00410 } 00411 00412 protected: 00413 EXPR expr_; 00414 }; 00415 00416 template <class Expr> 00417 struct ResultTraits0<UnaryFunctor<Expr> > 00418 { 00419 typedef typename ResultTraits0<Expr>::Res Res; 00420 }; 00421 00422 template <class Expr, class T1> 00423 struct ResultTraits1<UnaryFunctor<Expr>, T1> 00424 { 00425 typedef typename ResultTraits1<Expr, T1>::Res Res; 00426 }; 00427 00428 template <class Expr, class T1, class T2> 00429 struct ResultTraits2<UnaryFunctor<Expr>, T1, T2> 00430 { 00431 typedef typename ResultTraits2<Expr, T1, T2>::Res Res; 00432 }; 00433 00434 template <class Expr, class T1, class T2, class T3> 00435 struct ResultTraits3<UnaryFunctor<Expr>, T1, T2, T3> 00436 { 00437 typedef typename ResultTraits3<Expr, T1, T2, T3>::Res Res; 00438 }; 00439 00440 /************************************************************/ 00441 /* */ 00442 /* unary functors for arguments */ 00443 /* */ 00444 /************************************************************/ 00445 00446 struct ArgumentFunctor1; 00447 struct ArgumentFunctor2; 00448 struct ArgumentFunctor3; 00449 00450 template <> 00451 struct UnaryFunctor<ArgumentFunctor1> 00452 { 00453 UnaryFunctor() 00454 {} 00455 00456 template <class T1> 00457 T1 const & operator()(T1 const & v1) const 00458 { 00459 return v1; 00460 } 00461 00462 template <class T1, class T2> 00463 T1 const & operator()(T1 const & v1, T2 const &) const 00464 { 00465 return v1; 00466 } 00467 00468 template <class T1, class T2, class T3> 00469 T1 const & operator()(T1 const & v1, T2 const &, T3 const &) const 00470 { 00471 return v1; 00472 } 00473 }; 00474 00475 template <> 00476 struct ResultTraits0<UnaryFunctor<ArgumentFunctor1> > 00477 { 00478 typedef ErrorType Res; 00479 }; 00480 00481 template <class T1> 00482 struct ResultTraits1<UnaryFunctor<ArgumentFunctor1>, T1> 00483 { 00484 typedef T1 Res; 00485 }; 00486 00487 template <class T1, class T2> 00488 struct ResultTraits2<UnaryFunctor<ArgumentFunctor1>, T1, T2> 00489 { 00490 typedef T1 Res; 00491 }; 00492 00493 template <class T1, class T2, class T3> 00494 struct ResultTraits3<UnaryFunctor<ArgumentFunctor1>, T1, T2, T3> 00495 { 00496 typedef T1 Res; 00497 }; 00498 00499 /************************************************************/ 00500 00501 inline 00502 UnaryFunctor<ArgumentFunctor1> 00503 Arg1() 00504 { 00505 return UnaryFunctor<ArgumentFunctor1>(); 00506 } 00507 00508 /************************************************************/ 00509 00510 template <> 00511 struct UnaryFunctor<ArgumentFunctor2> 00512 { 00513 UnaryFunctor() 00514 {} 00515 00516 template <class T1, class T2> 00517 T2 const & operator()(T1 const &, T2 const & v2) const 00518 { 00519 return v2; 00520 } 00521 00522 template <class T1, class T2, class T3> 00523 T2 const & operator()(T1 const &, T2 const & v2, T3 const &) const 00524 { 00525 return v2; 00526 } 00527 }; 00528 00529 template <> 00530 struct ResultTraits0<UnaryFunctor<ArgumentFunctor2> > 00531 { 00532 typedef ErrorType Res; 00533 }; 00534 00535 template <class T1> 00536 struct ResultTraits1<UnaryFunctor<ArgumentFunctor2>, T1> 00537 { 00538 typedef ErrorType Res; 00539 }; 00540 00541 template <class T1, class T2> 00542 struct ResultTraits2<UnaryFunctor<ArgumentFunctor2>, T1, T2> 00543 { 00544 typedef T2 Res; 00545 }; 00546 00547 template <class T1, class T2, class T3> 00548 struct ResultTraits3<UnaryFunctor<ArgumentFunctor2>, T1, T2, T3> 00549 { 00550 typedef T2 Res; 00551 }; 00552 00553 /************************************************************/ 00554 00555 inline 00556 UnaryFunctor<ArgumentFunctor2> 00557 Arg2() 00558 { 00559 return UnaryFunctor<ArgumentFunctor2>(); 00560 } 00561 00562 /************************************************************/ 00563 00564 template <> 00565 struct UnaryFunctor<ArgumentFunctor3> 00566 { 00567 UnaryFunctor() 00568 {} 00569 00570 template <class T1, class T2, class T3> 00571 T3 const & operator()(T1 const &, T2 const &, T3 const & v3) const 00572 { 00573 return v3; 00574 } 00575 }; 00576 00577 template <> 00578 struct ResultTraits0<UnaryFunctor<ArgumentFunctor3> > 00579 { 00580 typedef ErrorType Res; 00581 }; 00582 00583 template <class T1> 00584 struct ResultTraits1<UnaryFunctor<ArgumentFunctor3>, T1> 00585 { 00586 typedef ErrorType Res; 00587 }; 00588 00589 template <class T1, class T2> 00590 struct ResultTraits2<UnaryFunctor<ArgumentFunctor3>, T1, T2> 00591 { 00592 typedef ErrorType Res; 00593 }; 00594 00595 template <class T1, class T2, class T3> 00596 struct ResultTraits3<UnaryFunctor<ArgumentFunctor3>, T1, T2, T3> 00597 { 00598 typedef T3 Res; 00599 }; 00600 00601 /************************************************************/ 00602 00603 inline 00604 UnaryFunctor<ArgumentFunctor3> 00605 Arg3() 00606 { 00607 return UnaryFunctor<ArgumentFunctor3>(); 00608 } 00609 00610 /************************************************************/ 00611 /* */ 00612 /* constant parameters */ 00613 /* */ 00614 /************************************************************/ 00615 00616 template <class T> 00617 struct ParameterFunctor 00618 { 00619 ParameterFunctor(T v) 00620 : value_(v) 00621 {} 00622 00623 T const & operator()() const 00624 { 00625 return value_; 00626 } 00627 00628 template <class U1> 00629 T const & operator()(U1 const &) const 00630 { 00631 return value_; 00632 } 00633 00634 template <class U1, class U2> 00635 T const & operator()(U1 const &, U2 const &) const 00636 { 00637 return value_; 00638 } 00639 00640 template <class U1, class U2, class U3> 00641 T const & operator()(U1 const &, U2 const &, U3 const &) const 00642 { 00643 return value_; 00644 } 00645 00646 protected: 00647 T value_; 00648 }; 00649 00650 template <class T> 00651 struct ResultTraits0<ParameterFunctor<T> > 00652 { 00653 typedef T Res; 00654 }; 00655 00656 template <class T, class T1> 00657 struct ResultTraits1<ParameterFunctor<T>, T1> 00658 { 00659 typedef T Res; 00660 }; 00661 00662 template <class T, class T1, class T2> 00663 struct ResultTraits2<ParameterFunctor<T>, T1, T2> 00664 { 00665 typedef T Res; 00666 }; 00667 00668 template <class T, class T1, class T2, class T3> 00669 struct ResultTraits3<ParameterFunctor<T>, T1, T2, T3> 00670 { 00671 typedef T Res; 00672 }; 00673 00674 template <class T> 00675 UnaryFunctor<ParameterFunctor<T> > 00676 Param(T const & v) 00677 { 00678 ParameterFunctor<T> fv(v); 00679 return UnaryFunctor<ParameterFunctor<T> >(fv); 00680 } 00681 00682 /************************************************************/ 00683 /* */ 00684 /* unary analyser base template */ 00685 /* */ 00686 /************************************************************/ 00687 00688 00689 template <class EXPR> 00690 class UnaryAnalyser 00691 { 00692 public: 00693 UnaryAnalyser(EXPR const & e) 00694 : expr_(e) 00695 {} 00696 00697 void operator()() const 00698 { 00699 expr_(); 00700 } 00701 00702 template <class T1> 00703 void operator()(T1 const & v) const 00704 { 00705 expr_(v); 00706 } 00707 00708 template <class T1, class T2> 00709 void operator()(T1 const & v1, T2 const & v2) const 00710 { 00711 expr_(v1, v2); 00712 } 00713 00714 template <class T1, class T2, class T3> 00715 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00716 { 00717 expr_(v1, v2, v3); 00718 } 00719 protected: 00720 00721 EXPR expr_; 00722 }; 00723 00724 /************************************************************/ 00725 /* */ 00726 /* variable assignment */ 00727 /* */ 00728 /************************************************************/ 00729 00730 template <class T> 00731 struct VarFunctor; 00732 00733 template <class T> 00734 struct UnaryFunctor<VarFunctor<T> >; 00735 00736 /************************************************************/ 00737 00738 #define MAKE_ASSIGNMENT_FUNCTOR(name, op) \ 00739 template <class V, class EXPR> \ 00740 struct AssignmentFunctor_##name \ 00741 { \ 00742 AssignmentFunctor_##name(UnaryFunctor<VarFunctor<V> > v, \ 00743 UnaryFunctor<EXPR> const & e) \ 00744 : value_(v.value_), expr_(e) \ 00745 {} \ 00746 \ 00747 V & operator()() const \ 00748 { \ 00749 const_cast<V &>(value_) op expr_(); \ 00750 return const_cast<V &>(value_); \ 00751 } \ 00752 \ 00753 template <class T1> \ 00754 V & operator()(T1 const & v1) const \ 00755 { \ 00756 const_cast<V &>(value_) op expr_(v1); \ 00757 return const_cast<V &>(value_); \ 00758 } \ 00759 \ 00760 template <class T1, class T2> \ 00761 V & operator()(T1 const & v1, T2 const & v2) const \ 00762 { \ 00763 const_cast<V &>(value_) op expr_(v1, v2); \ 00764 return const_cast<V &>(value_); \ 00765 } \ 00766 \ 00767 template <class T1, class T2, class T3> \ 00768 V & operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 00769 { \ 00770 const_cast<V &>(value_) op expr_(v1, v2, v3); \ 00771 return const_cast<V &>(value_); \ 00772 } \ 00773 \ 00774 private: \ 00775 V & value_; \ 00776 UnaryFunctor<EXPR> expr_; \ 00777 }; 00778 00779 /************************************************************/ 00780 00781 MAKE_ASSIGNMENT_FUNCTOR(assign, =) 00782 MAKE_ASSIGNMENT_FUNCTOR(add, +=) 00783 MAKE_ASSIGNMENT_FUNCTOR(subtract, -=) 00784 MAKE_ASSIGNMENT_FUNCTOR(multiply, *=) 00785 MAKE_ASSIGNMENT_FUNCTOR(divide, /=) 00786 00787 #undef MAKE_ASSIGNMENT_FUNCTOR 00788 00789 /************************************************************/ 00790 /* */ 00791 /* variables */ 00792 /* */ 00793 /************************************************************/ 00794 00795 template <class T> 00796 struct UnaryFunctor<VarFunctor<T> > 00797 { 00798 typedef T Res; 00799 00800 UnaryFunctor(T & v) 00801 : value_(v) 00802 {} 00803 00804 template <class EXPR> 00805 UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > > 00806 operator=(UnaryFunctor<EXPR> const & e) 00807 { 00808 AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > va(*this, e); 00809 return UnaryAnalyser< AssignmentFunctor_assign<T, UnaryFunctor<EXPR> > >(va); 00810 } 00811 00812 template <class EXPR> 00813 UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > > 00814 operator+=(UnaryFunctor<EXPR> const & e) 00815 { 00816 AssignmentFunctor_add<T, UnaryFunctor<EXPR> > va(*this, e); 00817 return UnaryAnalyser< AssignmentFunctor_add<T, UnaryFunctor<EXPR> > >(va); 00818 } 00819 00820 template <class EXPR> 00821 UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > > 00822 operator-=(UnaryFunctor<EXPR> const & e) 00823 { 00824 AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > va(*this, e); 00825 return UnaryAnalyser< AssignmentFunctor_subtract<T, UnaryFunctor<EXPR> > >(va); 00826 } 00827 00828 template <class EXPR> 00829 UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > > 00830 operator*=(UnaryFunctor<EXPR> const & e) 00831 { 00832 AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > va(*this, e); 00833 return UnaryAnalyser< AssignmentFunctor_multiply<T, UnaryFunctor<EXPR> > >(va); 00834 } 00835 00836 template <class EXPR> 00837 UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > > 00838 operator/=(UnaryFunctor<EXPR> const & e) 00839 { 00840 AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > va(*this, e); 00841 return UnaryAnalyser< AssignmentFunctor_divide<T, UnaryFunctor<EXPR> > >(va); 00842 } 00843 00844 T const & operator()() const 00845 { 00846 return value_; 00847 } 00848 00849 template <class U1> 00850 T const & operator()(U1 const &) const 00851 { 00852 return value_; 00853 } 00854 00855 template <class U1, class U2> 00856 T const & operator()(U1 const &, U2 const &) const 00857 { 00858 return value_; 00859 } 00860 00861 template <class U1, class U2, class U3> 00862 T const & operator()(U1 const &, U2 const &, U3 const &) const 00863 { 00864 return value_; 00865 } 00866 00867 T & value_; 00868 }; 00869 00870 template <class T> 00871 struct ResultTraits0<UnaryFunctor<VarFunctor<T> > > 00872 { 00873 typedef T Res; 00874 }; 00875 00876 template <class T, class T1> 00877 struct ResultTraits1<UnaryFunctor<VarFunctor<T> >, T1> 00878 { 00879 typedef T Res; 00880 }; 00881 00882 template <class T, class T1, class T2> 00883 struct ResultTraits2<UnaryFunctor<VarFunctor<T> >, T1, T2> 00884 { 00885 typedef T Res; 00886 }; 00887 00888 template <class T, class T1, class T2, class T3> 00889 struct ResultTraits3<UnaryFunctor<VarFunctor<T> >, T1, T2, T3> 00890 { 00891 typedef T Res; 00892 }; 00893 00894 template <class T> 00895 UnaryFunctor<VarFunctor<T> > 00896 Var(T & v) 00897 { 00898 return UnaryFunctor<VarFunctor<T> >(v); 00899 } 00900 00901 /************************************************************/ 00902 /* */ 00903 /* if then */ 00904 /* */ 00905 /************************************************************/ 00906 00907 template <class EXPR1, class EXPR2> 00908 struct IfThenFunctor 00909 { 00910 typedef void Res; 00911 00912 IfThenFunctor(EXPR1 const & e1, EXPR2 const & e2) 00913 : expr1_(e1), expr2_(e2) 00914 {} 00915 00916 void operator()() const 00917 { 00918 if( expr1_() ) expr2_(); 00919 } 00920 00921 template <class T> 00922 void operator()(T const & v1) const 00923 { 00924 if( expr1_(v1) ) expr2_(v1); 00925 } 00926 00927 template <class T1, class T2> 00928 void operator()(T1 const & v1, T2 const & v2) const 00929 { 00930 if( expr1_(v1, v2) ) expr2_(v1, v2); 00931 } 00932 00933 template <class T1, class T2, class T3> 00934 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00935 { 00936 if( expr1_(v1, v2, v3) ) expr2_(v1, v2, v3); 00937 } 00938 00939 private: 00940 00941 EXPR1 expr1_; 00942 EXPR2 expr2_; 00943 }; 00944 00945 template <class EXPR1, class EXPR2> 00946 UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00947 UnaryAnalyser<EXPR2> > > 00948 ifThen(UnaryFunctor<EXPR1> const & e1, 00949 UnaryAnalyser<EXPR2> const & e2) 00950 { 00951 IfThenFunctor<UnaryFunctor<EXPR1>, 00952 UnaryAnalyser<EXPR2> > p(e1, e2); 00953 return UnaryAnalyser<IfThenFunctor<UnaryFunctor<EXPR1>, 00954 UnaryAnalyser<EXPR2> > >(p); 00955 } 00956 00957 /************************************************************/ 00958 /* */ 00959 /* if then else */ 00960 /* */ 00961 /************************************************************/ 00962 00963 template <class EXPR1, class EXPR2, class EXPR3> 00964 struct IfThenElseFunctor; 00965 00966 template <class EXPR1, class EXPR2, class EXPR3> 00967 struct ResultTraits0<IfThenElseFunctor<EXPR1, EXPR2, EXPR3> > 00968 { 00969 typedef typename ResultTraits0<EXPR2>::Res R2; 00970 typedef typename ResultTraits0<EXPR3>::Res R3; 00971 typedef typename PromoteTraits<R2, R3>::Promote Res; 00972 }; 00973 00974 template <class EXPR1, class EXPR2, class EXPR3, class T1> 00975 struct ResultTraits1<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1> 00976 { 00977 typedef typename ResultTraits1<EXPR2, T1>::Res R2; 00978 typedef typename ResultTraits1<EXPR3, T1>::Res R3; 00979 typedef typename PromoteTraits<R2, R3>::Promote Res; 00980 }; 00981 00982 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2> 00983 struct ResultTraits2<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2> 00984 { 00985 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; 00986 typedef typename ResultTraits2<EXPR3, T1, T2>::Res R3; 00987 typedef typename PromoteTraits<R2, R3>::Promote Res; 00988 }; 00989 00990 template <class EXPR1, class EXPR2, class EXPR3, class T1, class T2, class T3> 00991 struct ResultTraits3<IfThenElseFunctor<EXPR1, EXPR2, EXPR3>, T1, T2, T3> 00992 { 00993 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; 00994 typedef typename ResultTraits3<EXPR3, T1, T2, T3>::Res R3; 00995 typedef typename PromoteTraits<R2, R3>::Promote Res; 00996 }; 00997 00998 template <class EXPR1, class EXPR2, class EXPR3> 00999 struct IfThenElseFunctor 01000 { 01001 IfThenElseFunctor(EXPR1 const & e1, EXPR2 const & e2, EXPR3 const & e3) 01002 : expr1_(e1), expr2_(e2), expr3_(e3) 01003 {} 01004 01005 typename ResultTraits0<IfThenElseFunctor>::Res 01006 operator()() const 01007 { 01008 typename 01009 ResultTraits0<IfThenElseFunctor>::Res 01010 r2(expr2_()); 01011 typename 01012 ResultTraits0<IfThenElseFunctor>::Res 01013 r3(expr3_()); 01014 return expr1_() ? r2 : r3; 01015 } 01016 01017 template <class T> 01018 typename ResultTraits1<IfThenElseFunctor, T>::Res 01019 operator()(T const & v1) const 01020 { 01021 typename 01022 ResultTraits1<IfThenElseFunctor, T>::Res 01023 r2(expr2_(v1)); 01024 typename 01025 ResultTraits1<IfThenElseFunctor, T>::Res 01026 r3(expr3_(v1)); 01027 return expr1_(v1) ? r2 : r3; 01028 } 01029 01030 template <class T1, class T2> 01031 typename ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01032 operator()(T1 const & v1, T2 const & v2) const 01033 { 01034 typename 01035 ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01036 r2(expr2_(v1, v2)); 01037 typename 01038 ResultTraits2<IfThenElseFunctor, T1, T2>::Res 01039 r3(expr3_(v1, v2)); 01040 return expr1_(v1, v2) ? r2 : r3; 01041 } 01042 01043 template <class T1, class T2, class T3> 01044 typename ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01045 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01046 { 01047 typename 01048 ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01049 r2(expr2_(v1, v2, v3)); 01050 typename 01051 ResultTraits3<IfThenElseFunctor, T1, T2, T3>::Res 01052 r3(expr3_(v1, v2, v3)); 01053 return expr1_(v1, v2, v3) ? r2 : r3; 01054 } 01055 01056 private: 01057 01058 EXPR1 expr1_; 01059 EXPR2 expr2_; 01060 EXPR3 expr3_; 01061 }; 01062 01063 template <class EXPR1, class EXPR2, class EXPR3> 01064 UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01065 UnaryFunctor<EXPR2>, 01066 UnaryFunctor<EXPR3> > > 01067 ifThenElse(UnaryFunctor<EXPR1> const & e1, 01068 UnaryFunctor<EXPR2> const & e2, 01069 UnaryFunctor<EXPR3> const & e3) 01070 { 01071 IfThenElseFunctor<UnaryFunctor<EXPR1>, 01072 UnaryFunctor<EXPR2>, 01073 UnaryFunctor<EXPR3> > p(e1, e2, e3); 01074 return UnaryFunctor<IfThenElseFunctor<UnaryFunctor<EXPR1>, 01075 UnaryFunctor<EXPR2>, 01076 UnaryFunctor<EXPR3> > >(p); 01077 } 01078 01079 /************************************************************/ 01080 /* */ 01081 /* functors for unary functions */ 01082 /* */ 01083 /************************************************************/ 01084 01085 #define MAKE_FUNCTOR_UNARY_FUNCTION(function, namespc) \ 01086 using ::namespc::function; \ 01087 template <class EXPR> \ 01088 struct Functor_##function; \ 01089 \ 01090 template <class EXPR> \ 01091 struct ResultTraits0<Functor_##function<EXPR> > \ 01092 { \ 01093 typedef typename ResultTraits0<EXPR>::Res R1; \ 01094 typedef typename NumericTraits<R1>::RealPromote Res; \ 01095 }; \ 01096 \ 01097 template <class EXPR, class T1> \ 01098 struct ResultTraits1<Functor_##function<EXPR>, T1> \ 01099 { \ 01100 typedef typename ResultTraits1<EXPR, T1>::Res R1; \ 01101 typedef typename NumericTraits<R1>::RealPromote Res; \ 01102 }; \ 01103 \ 01104 template <class EXPR, class T1, class T2> \ 01105 struct ResultTraits2<Functor_##function<EXPR>, T1, T2> \ 01106 { \ 01107 typedef typename ResultTraits2<EXPR, T1, T2>::Res R1; \ 01108 typedef typename NumericTraits<R1>::RealPromote Res; \ 01109 }; \ 01110 \ 01111 template <class EXPR, class T1, class T2, class T3> \ 01112 struct ResultTraits3<Functor_##function<EXPR>, T1, T2, T3> \ 01113 { \ 01114 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res R1; \ 01115 typedef typename NumericTraits<R1>::RealPromote Res; \ 01116 }; \ 01117 \ 01118 template <class EXPR> \ 01119 struct Functor_##function \ 01120 { \ 01121 Functor_##function(EXPR const & e) \ 01122 : expr_(e) \ 01123 {} \ 01124 \ 01125 typename ResultTraits0<Functor_##function>::Res \ 01126 operator()() const \ 01127 { \ 01128 return function(expr_()); \ 01129 } \ 01130 \ 01131 template <class T> \ 01132 typename ResultTraits1<Functor_##function, T>::Res \ 01133 operator()(T const & v1) const \ 01134 { \ 01135 return function(expr_(v1)); \ 01136 } \ 01137 \ 01138 template <class T1, class T2> \ 01139 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01140 operator()(T1 const & v1, T2 const & v2) const \ 01141 { \ 01142 return function(expr_(v1, v2)); \ 01143 } \ 01144 \ 01145 template <class T1, class T2, class T3> \ 01146 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01147 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01148 { \ 01149 return function(expr_(v1, v2, v3)); \ 01150 } \ 01151 \ 01152 protected: \ 01153 \ 01154 EXPR expr_; \ 01155 }; \ 01156 \ 01157 template <class EXPR> \ 01158 UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > > \ 01159 function(UnaryFunctor<EXPR> const & e) \ 01160 { \ 01161 Functor_##function<UnaryFunctor<EXPR> > p(e); \ 01162 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR> > >(p); \ 01163 } 01164 01165 /************************************************************/ 01166 01167 MAKE_FUNCTOR_UNARY_FUNCTION(sqrt, std) 01168 MAKE_FUNCTOR_UNARY_FUNCTION(exp, std) 01169 MAKE_FUNCTOR_UNARY_FUNCTION(log, std) 01170 MAKE_FUNCTOR_UNARY_FUNCTION(log10, std) 01171 MAKE_FUNCTOR_UNARY_FUNCTION(sin, std) 01172 MAKE_FUNCTOR_UNARY_FUNCTION(asin, std) 01173 MAKE_FUNCTOR_UNARY_FUNCTION(cos, std) 01174 MAKE_FUNCTOR_UNARY_FUNCTION(acos, std) 01175 MAKE_FUNCTOR_UNARY_FUNCTION(tan, std) 01176 MAKE_FUNCTOR_UNARY_FUNCTION(atan, std) 01177 MAKE_FUNCTOR_UNARY_FUNCTION(floor, std) 01178 MAKE_FUNCTOR_UNARY_FUNCTION(ceil, std) 01179 MAKE_FUNCTOR_UNARY_FUNCTION(abs, vigra) 01180 //MAKE_FUNCTOR_UNARY_FUNCTION(norm, vigra) 01181 //MAKE_FUNCTOR_UNARY_FUNCTION(squaredNorm, vigra) 01182 01183 #undef MAKE_FUNCTOR_UNARY_FUNCTION 01184 01185 /************************************************************/ 01186 /* */ 01187 /* functors for unary operators */ 01188 /* */ 01189 /************************************************************/ 01190 01191 #define MAKE_FUNCTOR_UNARY_OPERATOR(name, op) \ 01192 template <class EXPR> \ 01193 struct Functor_##name; \ 01194 \ 01195 template <class EXPR> \ 01196 struct ResultTraits0<Functor_##name<EXPR> > \ 01197 { \ 01198 typedef typename ResultTraits0<EXPR>::Res Res; \ 01199 }; \ 01200 \ 01201 template <class EXPR, class T1> \ 01202 struct ResultTraits1<Functor_##name<EXPR>, T1> \ 01203 { \ 01204 typedef typename ResultTraits1<EXPR, T1>::Res Res; \ 01205 }; \ 01206 \ 01207 template <class EXPR, class T1, class T2> \ 01208 struct ResultTraits2<Functor_##name<EXPR>, T1, T2> \ 01209 { \ 01210 typedef typename ResultTraits2<EXPR, T1, T2>::Res Res; \ 01211 }; \ 01212 \ 01213 template <class EXPR, class T1, class T2, class T3> \ 01214 struct ResultTraits3<Functor_##name<EXPR>, T1, T2, T3> \ 01215 { \ 01216 typedef typename ResultTraits3<EXPR, T1, T2, T3>::Res Res; \ 01217 }; \ 01218 \ 01219 template <class EXPR> \ 01220 struct Functor_##name \ 01221 { \ 01222 Functor_##name(EXPR const & e) \ 01223 : expr_(e) \ 01224 {} \ 01225 \ 01226 typename ResultTraits0<Functor_##name>::Res \ 01227 operator()() const \ 01228 { \ 01229 return op expr_(); \ 01230 } \ 01231 \ 01232 template <class T> \ 01233 typename ResultTraits1<Functor_##name, T>::Res \ 01234 operator()(T const & v1) const \ 01235 { \ 01236 return op expr_(v1); \ 01237 } \ 01238 \ 01239 template <class T1, class T2> \ 01240 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01241 operator()(T1 const & v1, T2 const & v2) const \ 01242 { \ 01243 return op expr_(v1, v2); \ 01244 } \ 01245 \ 01246 template <class T1, class T2, class T3> \ 01247 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01248 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01249 { \ 01250 return op expr_(v1, v2, v3); \ 01251 } \ 01252 protected: \ 01253 \ 01254 EXPR expr_; \ 01255 }; \ 01256 \ 01257 template <class EXPR> \ 01258 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > > \ 01259 operator op(UnaryFunctor<EXPR> const & e) \ 01260 { \ 01261 Functor_##name<UnaryFunctor<EXPR> > p(e); \ 01262 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR> > >(p); \ 01263 } 01264 01265 01266 /************************************************************/ 01267 01268 MAKE_FUNCTOR_UNARY_OPERATOR(minus, -) 01269 MAKE_FUNCTOR_UNARY_OPERATOR(negate, !) 01270 MAKE_FUNCTOR_UNARY_OPERATOR(bitNegate, ~) 01271 01272 #undef MAKE_FUNCTOR_UNARY_OPERATOR 01273 01274 /************************************************************/ 01275 /* */ 01276 /* functors for binary functions */ 01277 /* */ 01278 /************************************************************/ 01279 01280 #define MAKE_FUNCTOR_BINARY_FUNCTION(function) \ 01281 using std::function; \ 01282 template <class EXPR1, class EXPR2> \ 01283 struct Functor_##function; \ 01284 \ 01285 template <class EXPR1, class EXPR2> \ 01286 struct ResultTraits0<Functor_##function<EXPR1, EXPR2> > \ 01287 { \ 01288 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01289 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01290 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01291 typedef typename NumericTraits<R3>::RealPromote Res; \ 01292 }; \ 01293 \ 01294 template <class EXPR1, class EXPR2, class T1> \ 01295 struct ResultTraits1<Functor_##function<EXPR1, EXPR2>, T1> \ 01296 { \ 01297 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01298 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01299 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01300 typedef typename NumericTraits<R3>::RealPromote Res; \ 01301 }; \ 01302 \ 01303 template <class EXPR1, class EXPR2, class T1, class T2> \ 01304 struct ResultTraits2<Functor_##function<EXPR1, EXPR2>, T1, T2> \ 01305 { \ 01306 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01307 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01308 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01309 typedef typename NumericTraits<R3>::RealPromote Res; \ 01310 }; \ 01311 \ 01312 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01313 struct ResultTraits3<Functor_##function<EXPR1, EXPR2>, T1, T2, T3> \ 01314 { \ 01315 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01316 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01317 typedef typename PromoteTraits<R1, R2>::Promote R3; \ 01318 typedef typename NumericTraits<R3>::RealPromote Res; \ 01319 }; \ 01320 \ 01321 template <class EXPR1, class EXPR2> \ 01322 struct Functor_##function \ 01323 { \ 01324 Functor_##function(EXPR1 const & e1, EXPR2 const & e2) \ 01325 : expr1_(e1), expr2_(e2) \ 01326 {} \ 01327 \ 01328 typename ResultTraits0<Functor_##function>::Res \ 01329 operator()() const \ 01330 { \ 01331 return function(expr1_(), expr2_()); \ 01332 } \ 01333 \ 01334 template <class T> \ 01335 typename ResultTraits1<Functor_##function, T>::Res \ 01336 operator()(T const & v1) const \ 01337 { \ 01338 return function(expr1_(v1), expr2_(v1)); \ 01339 } \ 01340 \ 01341 template <class T1, class T2> \ 01342 typename ResultTraits2<Functor_##function, T1, T2>::Res \ 01343 operator()(T1 const & v1, T2 const & v2) const \ 01344 { \ 01345 return function(expr1_(v1, v2), expr2_(v1, v2)); \ 01346 } \ 01347 \ 01348 template <class T1, class T2, class T3> \ 01349 typename ResultTraits3<Functor_##function, T1, T2, T3>::Res \ 01350 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01351 { \ 01352 return function(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); \ 01353 } \ 01354 \ 01355 private: \ 01356 \ 01357 EXPR1 expr1_; \ 01358 EXPR2 expr2_; \ 01359 }; \ 01360 \ 01361 template <class EXPR1, class EXPR2> \ 01362 UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01363 function(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01364 { \ 01365 Functor_##function<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01366 return UnaryFunctor<Functor_##function<UnaryFunctor<EXPR1>, \ 01367 UnaryFunctor<EXPR2> > >(p); \ 01368 } 01369 01370 /************************************************************/ 01371 01372 MAKE_FUNCTOR_BINARY_FUNCTION(pow) 01373 MAKE_FUNCTOR_BINARY_FUNCTION(atan2) 01374 MAKE_FUNCTOR_BINARY_FUNCTION(fmod) 01375 01376 #undef MAKE_FUNCTOR_BINARY_FUNCTION 01377 01378 /************************************************************/ 01379 01380 #define MAKE_FUNCTOR_MINMAX(name, op) \ 01381 template <class EXPR1, class EXPR2> \ 01382 struct Functor_##name; \ 01383 \ 01384 template <class EXPR1, class EXPR2> \ 01385 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01386 { \ 01387 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01388 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01389 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01390 }; \ 01391 \ 01392 template <class EXPR1, class EXPR2, class T1> \ 01393 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01394 { \ 01395 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01396 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01397 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01398 }; \ 01399 \ 01400 template <class EXPR1, class EXPR2, class T1, class T2> \ 01401 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01402 { \ 01403 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01404 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01405 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01406 }; \ 01407 \ 01408 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01409 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01410 { \ 01411 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01412 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01413 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01414 }; \ 01415 \ 01416 template <class EXPR1, class EXPR2> \ 01417 struct Functor_##name \ 01418 { \ 01419 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01420 : expr1_(e1), expr2_(e2) \ 01421 {} \ 01422 \ 01423 typename ResultTraits0<Functor_##name>::Res \ 01424 operator()() const \ 01425 { \ 01426 typename \ 01427 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R1 r1(expr1_()); \ 01428 typename \ 01429 ResultTraits0<Functor_##name<EXPR1, EXPR2> >::R2 r2(expr2_()); \ 01430 return (r1 op r2) ? r1 : r2; \ 01431 } \ 01432 \ 01433 template <class T> \ 01434 typename ResultTraits1<Functor_##name, T>::Res \ 01435 operator()(T const & v1) const \ 01436 { \ 01437 typename \ 01438 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R1 r1(expr1_(v1)); \ 01439 typename \ 01440 ResultTraits1<Functor_##name<EXPR1, EXPR2>, T>::R2 r2(expr2_(v1)); \ 01441 return (r1 op r2) ? r1 : r2; \ 01442 } \ 01443 \ 01444 template <class T1, class T2> \ 01445 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01446 operator()(T1 const & v1, T2 const & v2) const \ 01447 { \ 01448 typename \ 01449 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R1 r1(expr1_(v1, v2)); \ 01450 typename \ 01451 ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2>::R2 r2(expr2_(v1, v2)); \ 01452 return (r1 op r2) ? r1 : r2; \ 01453 } \ 01454 \ 01455 template <class T1, class T2, class T3> \ 01456 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01457 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01458 { \ 01459 typename \ 01460 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R1 r1(expr1_(v1, v2, v3)); \ 01461 typename \ 01462 ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3>::R2 r2(expr2_(v1, v2, v3)); \ 01463 return (r1 op r2) ? r1 : r2; \ 01464 } \ 01465 \ 01466 private: \ 01467 \ 01468 EXPR1 expr1_; \ 01469 EXPR2 expr2_; \ 01470 }; \ 01471 \ 01472 template <class EXPR1, class EXPR2> \ 01473 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01474 name(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01475 { \ 01476 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01477 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01478 UnaryFunctor<EXPR2> > >(p); \ 01479 } 01480 01481 MAKE_FUNCTOR_MINMAX(min, <) 01482 MAKE_FUNCTOR_MINMAX(max, >) 01483 01484 #undef MAKE_FUNCTOR_MINMAX 01485 01486 /************************************************************/ 01487 /* */ 01488 /* functors for binary operators */ 01489 /* */ 01490 /************************************************************/ 01491 01492 #define MAKE_FUNCTOR_BINARY_OPERATOR(name, op) \ 01493 template <class EXPR1, class EXPR2> \ 01494 struct Functor_##name; \ 01495 \ 01496 template <class EXPR1, class EXPR2> \ 01497 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01498 { \ 01499 typedef typename ResultTraits0<EXPR1>::Res R1; \ 01500 typedef typename ResultTraits0<EXPR2>::Res R2; \ 01501 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01502 }; \ 01503 \ 01504 template <class EXPR1, class EXPR2, class T1> \ 01505 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01506 { \ 01507 typedef typename ResultTraits1<EXPR1, T1>::Res R1; \ 01508 typedef typename ResultTraits1<EXPR2, T1>::Res R2; \ 01509 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01510 }; \ 01511 \ 01512 template <class EXPR1, class EXPR2, class T1, class T2> \ 01513 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01514 { \ 01515 typedef typename ResultTraits2<EXPR1, T1, T2>::Res R1; \ 01516 typedef typename ResultTraits2<EXPR2, T1, T2>::Res R2; \ 01517 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01518 }; \ 01519 \ 01520 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01521 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01522 { \ 01523 typedef typename ResultTraits3<EXPR1, T1, T2, T3>::Res R1; \ 01524 typedef typename ResultTraits3<EXPR2, T1, T2, T3>::Res R2; \ 01525 typedef typename PromoteTraits<R1, R2>::Promote Res; \ 01526 }; \ 01527 \ 01528 template <class EXPR1, class EXPR2> \ 01529 struct Functor_##name \ 01530 { \ 01531 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01532 : expr1_(e1), expr2_(e2) \ 01533 {} \ 01534 \ 01535 typename ResultTraits0<Functor_##name>::Res \ 01536 operator()() const \ 01537 { \ 01538 return expr1_() op expr2_(); \ 01539 } \ 01540 \ 01541 template <class T> \ 01542 typename ResultTraits1<Functor_##name, T>::Res \ 01543 operator()(T const & v1) const \ 01544 { \ 01545 return expr1_(v1) op expr2_(v1); \ 01546 } \ 01547 \ 01548 template <class T1, class T2> \ 01549 typename ResultTraits2<Functor_##name, T1, T2>::Res \ 01550 operator()(T1 const & v1, T2 const & v2) const \ 01551 { \ 01552 return expr1_(v1, v2) op expr2_(v1, v2); \ 01553 } \ 01554 \ 01555 template <class T1, class T2, class T3> \ 01556 typename ResultTraits3<Functor_##name, T1, T2, T3>::Res \ 01557 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01558 { \ 01559 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01560 } \ 01561 \ 01562 private: \ 01563 \ 01564 EXPR1 expr1_; \ 01565 EXPR2 expr2_; \ 01566 }; \ 01567 \ 01568 template <class EXPR1, class EXPR2> \ 01569 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01570 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01571 { \ 01572 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01573 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01574 UnaryFunctor<EXPR2> > >(p); \ 01575 } 01576 01577 /************************************************************/ 01578 01579 MAKE_FUNCTOR_BINARY_OPERATOR(add, +) 01580 MAKE_FUNCTOR_BINARY_OPERATOR(subtract, -) 01581 MAKE_FUNCTOR_BINARY_OPERATOR(multiply, *) 01582 MAKE_FUNCTOR_BINARY_OPERATOR(divide, /) 01583 MAKE_FUNCTOR_BINARY_OPERATOR(modulo, %) 01584 MAKE_FUNCTOR_BINARY_OPERATOR(bitAnd, &) 01585 MAKE_FUNCTOR_BINARY_OPERATOR(bitOr, |) 01586 MAKE_FUNCTOR_BINARY_OPERATOR(bitXor, ^) 01587 01588 #undef MAKE_FUNCTOR_BINARY_OPERATOR 01589 01590 /************************************************************/ 01591 01592 #define MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(name, op) \ 01593 template <class EXPR1, class EXPR2> \ 01594 struct Functor_##name; \ 01595 \ 01596 template <class EXPR1, class EXPR2> \ 01597 struct ResultTraits0<Functor_##name<EXPR1, EXPR2> > \ 01598 { \ 01599 typedef bool Res; \ 01600 }; \ 01601 \ 01602 template <class EXPR1, class EXPR2, class T1> \ 01603 struct ResultTraits1<Functor_##name<EXPR1, EXPR2>, T1> \ 01604 { \ 01605 typedef bool Res; \ 01606 }; \ 01607 \ 01608 template <class EXPR1, class EXPR2, class T1, class T2> \ 01609 struct ResultTraits2<Functor_##name<EXPR1, EXPR2>, T1, T2> \ 01610 { \ 01611 typedef bool Res; \ 01612 }; \ 01613 \ 01614 template <class EXPR1, class EXPR2, class T1, class T2, class T3> \ 01615 struct ResultTraits3<Functor_##name<EXPR1, EXPR2>, T1, T2, T3> \ 01616 { \ 01617 typedef bool Res; \ 01618 }; \ 01619 \ 01620 template <class EXPR1, class EXPR2> \ 01621 struct Functor_##name \ 01622 { \ 01623 Functor_##name(EXPR1 const & e1, EXPR2 const & e2) \ 01624 : expr1_(e1), expr2_(e2) \ 01625 {} \ 01626 \ 01627 bool operator()() const \ 01628 { \ 01629 return expr1_() op expr2_(); \ 01630 } \ 01631 \ 01632 template <class T> \ 01633 bool operator()(T const & v1) const \ 01634 { \ 01635 return expr1_(v1) op expr2_(v1); \ 01636 } \ 01637 \ 01638 template <class T1, class T2> \ 01639 bool operator()(T1 const & v1, T2 const & v2) const \ 01640 { \ 01641 return expr1_(v1, v2) op expr2_(v1, v2); \ 01642 } \ 01643 \ 01644 template <class T1, class T2, class T3> \ 01645 bool operator()(T1 const & v1, T2 const & v2, T3 const & v3) const \ 01646 { \ 01647 return expr1_(v1, v2, v3) op expr2_(v1, v2, v3); \ 01648 } \ 01649 \ 01650 private: \ 01651 \ 01652 EXPR1 expr1_; \ 01653 EXPR2 expr2_; \ 01654 }; \ 01655 \ 01656 template <class EXPR1, class EXPR2> \ 01657 UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > > \ 01658 operator op(UnaryFunctor<EXPR1> const & e1, UnaryFunctor<EXPR2> const & e2) \ 01659 { \ 01660 Functor_##name<UnaryFunctor<EXPR1>, UnaryFunctor<EXPR2> > p(e1, e2); \ 01661 return UnaryFunctor<Functor_##name<UnaryFunctor<EXPR1>, \ 01662 UnaryFunctor<EXPR2> > >(p); \ 01663 } 01664 01665 /************************************************************/ 01666 01667 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(equals, ==) 01668 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(differs, !=) 01669 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(less, <) 01670 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(lessEqual, <=) 01671 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greater, >) 01672 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(greaterEqual, >=) 01673 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(and, &&) 01674 MAKE_FUNCTOR_BINARY_OPERATOR_BOOL(or, ||) 01675 01676 #undef MAKE_FUNCTOR_BINARY_OPERATOR_BOOL 01677 01678 /************************************************************/ 01679 /* */ 01680 /* unary apply */ 01681 /* */ 01682 /************************************************************/ 01683 01684 template <class EXPR, class RES, class ARG> 01685 struct UnaryFctPtrFunctor 01686 { 01687 UnaryFctPtrFunctor(EXPR const & e, RES (*fct)(ARG)) 01688 : expr_(e), f_(fct) 01689 {} 01690 01691 RES operator()() const 01692 { 01693 return f_(expr_()); 01694 } 01695 01696 template <class T> 01697 RES operator()(T const & v1) const 01698 { 01699 return f_(expr_(v1)); 01700 } 01701 01702 template <class T1, class T2> 01703 RES operator()(T1 const & v1, T2 const & v2) const 01704 { 01705 return f_(expr_(v1, v2)); 01706 } 01707 01708 template <class T1, class T2, class T3> 01709 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01710 { 01711 return f_(expr_(v1, v2, v3)); 01712 } 01713 protected: 01714 01715 EXPR expr_; 01716 RES (*f_)(ARG); 01717 }; 01718 01719 template <class EXPR, class RES, class ARG> 01720 struct ResultTraits0<UnaryFctPtrFunctor<EXPR, RES, ARG> > 01721 { 01722 typedef RES Res; 01723 }; 01724 01725 template <class EXPR, class RES, class ARG, class T1> 01726 struct ResultTraits1<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1> 01727 { 01728 typedef RES Res; 01729 }; 01730 01731 template <class EXPR, class RES, class ARG, class T1, class T2> 01732 struct ResultTraits2<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2> 01733 { 01734 typedef RES Res; 01735 }; 01736 01737 template <class EXPR, class RES, class ARG, class T1, class T2, class T3> 01738 struct ResultTraits3<UnaryFctPtrFunctor<EXPR, RES, ARG>, T1, T2, T3> 01739 { 01740 typedef RES Res; 01741 }; 01742 01743 template <class EXPR, class RES, class ARG> 01744 UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> > 01745 applyFct(RES (*f)(ARG), UnaryFunctor<EXPR> const & e) 01746 { 01747 UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> p(e, f); 01748 return UnaryFunctor<UnaryFctPtrFunctor<UnaryFunctor<EXPR>, RES, ARG> >(p); 01749 } 01750 01751 /************************************************************/ 01752 /* */ 01753 /* binary apply */ 01754 /* */ 01755 /************************************************************/ 01756 01757 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01758 struct BinaryFctPtrFunctor 01759 { 01760 BinaryFctPtrFunctor(EXPR1 const & e1, EXPR2 const & e2, 01761 RES (*f)(ARG1, ARG2)) 01762 : expr1_(e1), expr2_(e2), f_(f) 01763 {} 01764 01765 RES operator()() const 01766 { 01767 return f_(expr1_(), expr2_()); 01768 } 01769 01770 template <class T> 01771 RES operator()(T const & v1) const 01772 { 01773 return f_(expr1_(v1), expr2_(v1)); 01774 } 01775 01776 template <class T1, class T2> 01777 RES operator()(T1 const & v1, T2 const & v2) const 01778 { 01779 return f_(expr1_(v1, v2), expr2_(v1, v2)); 01780 } 01781 01782 template <class T1, class T2, class T3> 01783 RES operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01784 { 01785 return f_(expr1_(v1, v2, v3), expr2_(v1, v2, v3)); 01786 } 01787 protected: 01788 01789 EXPR1 expr1_; 01790 EXPR2 expr2_; 01791 RES (*f_)(ARG1, ARG2); 01792 }; 01793 01794 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01795 struct ResultTraits0<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2> > 01796 { 01797 typedef RES Res; 01798 }; 01799 01800 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01801 class T1> 01802 struct ResultTraits1<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1> 01803 { 01804 typedef RES Res; 01805 }; 01806 01807 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01808 class T1, class T2> 01809 struct ResultTraits2<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2> 01810 { 01811 typedef RES Res; 01812 }; 01813 01814 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2, 01815 class T1, class T2, class T3> 01816 struct ResultTraits3<BinaryFctPtrFunctor<EXPR1, EXPR2, RES, ARG1, ARG2>, T1, T2, T3> 01817 { 01818 typedef RES Res; 01819 }; 01820 01821 template <class EXPR1, class EXPR2, class RES, class ARG1, class ARG2> 01822 UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01823 UnaryFunctor<EXPR2>, 01824 RES, ARG1, ARG2> > 01825 applyFct(RES (*f)(ARG1, ARG2), UnaryFunctor<EXPR1> const & e1, 01826 UnaryFunctor<EXPR2> const & e2) 01827 { 01828 BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01829 UnaryFunctor<EXPR2>, 01830 RES, ARG1, ARG2> p(e1, e2, f); 01831 return UnaryFunctor<BinaryFctPtrFunctor<UnaryFunctor<EXPR1>, 01832 UnaryFunctor<EXPR2>, 01833 RES, ARG1, ARG2> >(p); 01834 } 01835 01836 /************************************************************/ 01837 /* */ 01838 /* comma operator */ 01839 /* */ 01840 /************************************************************/ 01841 01842 template <class EXPR1, class EXPR2> 01843 struct CommaFunctor 01844 { 01845 CommaFunctor(EXPR1 const & e1, EXPR2 const & e2) 01846 : expr1_(e1), expr2_(e2) 01847 {} 01848 01849 typename ResultTraits0<EXPR2>::Res 01850 operator()() const 01851 { 01852 expr1_(); 01853 return expr2_(); 01854 } 01855 01856 template <class T> 01857 typename ResultTraits1<EXPR2, T>::Res 01858 operator()(T const & v1) const 01859 { 01860 expr1_(v1); 01861 return expr2_(v1); 01862 } 01863 01864 template <class T1, class T2> 01865 typename ResultTraits2<EXPR2, T1, T2>::Res 01866 operator()(T1 const & v1, T2 const & v2) const 01867 { 01868 expr1_(v1, v2); 01869 return expr2_(v1, v2); 01870 } 01871 01872 template <class T1, class T2, class T3> 01873 typename ResultTraits3<EXPR2, T1, T2, T3>::Res 01874 operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01875 { 01876 expr1_(v1, v2, v3); 01877 return expr2_(v1, v2, v3); 01878 } 01879 01880 protected: 01881 01882 EXPR1 expr1_; 01883 EXPR2 expr2_; 01884 }; 01885 01886 template <class Expr1, class Expr2> 01887 struct ResultTraits0<CommaFunctor<Expr1, Expr2> > 01888 { 01889 typedef typename ResultTraits0<Expr2>::Res Res; 01890 }; 01891 01892 template <class Expr1, class Expr2, class T1> 01893 struct ResultTraits1<CommaFunctor<Expr1, Expr2>, T1> 01894 { 01895 typedef typename ResultTraits1<Expr2, T1>::Res Res; 01896 }; 01897 01898 template <class Expr1, class Expr2, class T1, class T2> 01899 struct ResultTraits2<CommaFunctor<Expr1, Expr2>, T1, T2> 01900 { 01901 typedef typename ResultTraits2<Expr2, T1, T2>::Res Res; 01902 }; 01903 01904 template <class Expr1, class Expr2, class T1, class T2, class T3> 01905 struct ResultTraits3<CommaFunctor<Expr1, Expr2>, T1, T2, T3> 01906 { 01907 typedef typename ResultTraits3<Expr2, T1, T2, T3>::Res Res; 01908 }; 01909 01910 template <class EXPR1, class EXPR2> 01911 UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01912 UnaryFunctor<EXPR2> > > 01913 operator,(UnaryAnalyser<EXPR1> const & e1, 01914 UnaryFunctor<EXPR2> const & e2) 01915 { 01916 CommaFunctor<UnaryAnalyser<EXPR1>, 01917 UnaryFunctor<EXPR2> > p(e1, e2); 01918 return UnaryFunctor<CommaFunctor<UnaryAnalyser<EXPR1>, 01919 UnaryFunctor<EXPR2> > >(p); 01920 } 01921 01922 /************************************************************/ 01923 01924 template <class EXPR1, class EXPR2> 01925 struct CommaAnalyser 01926 { 01927 CommaAnalyser(EXPR1 const & e1, EXPR2 const & e2) 01928 : expr1_(e1), expr2_(e2) 01929 {} 01930 01931 void operator()() const 01932 { 01933 expr1_(); 01934 expr2_(); 01935 } 01936 01937 template <class T> 01938 void operator()(T const & v1) const 01939 { 01940 expr1_(v1); 01941 expr2_(v1); 01942 } 01943 01944 template <class T1, class T2> 01945 void operator()(T1 const & v1, T2 const & v2) const 01946 { 01947 expr1_(v1, v2); 01948 expr2_(v1, v2); 01949 } 01950 01951 template <class T1, class T2, class T3> 01952 void operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 01953 { 01954 expr1_(v1, v2, v3); 01955 expr2_(v1, v2, v3); 01956 } 01957 01958 protected: 01959 01960 EXPR1 expr1_; 01961 EXPR2 expr2_; 01962 }; 01963 01964 template <class EXPR1, class EXPR2> 01965 UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 01966 UnaryAnalyser<EXPR2> > > 01967 operator,(UnaryAnalyser<EXPR1> const & e1, 01968 UnaryAnalyser<EXPR2> const & e2) 01969 { 01970 CommaAnalyser<UnaryAnalyser<EXPR1>, 01971 UnaryAnalyser<EXPR2> > p(e1, e2); 01972 return UnaryAnalyser<CommaAnalyser<UnaryAnalyser<EXPR1>, 01973 UnaryAnalyser<EXPR2> > >(p); 01974 } 01975 01976 } // namespace functor 01977 01978 #if defined(__GNUC__) && __GNUC__ < 3 01979 using functor::Arg1; 01980 using functor::Arg2; 01981 using functor::Arg3; 01982 using functor::Param; 01983 #endif 01984 01985 template <class T> 01986 class FunctorTraits<functor::UnaryFunctor<T> > 01987 : public FunctorTraitsBase<functor::UnaryFunctor<T> > 01988 { 01989 public: 01990 typedef VigraTrueType isInitializer; 01991 typedef VigraTrueType isUnaryFunctor; 01992 typedef VigraTrueType isBinaryFunctor; 01993 typedef VigraTrueType isTernaryFunctor; 01994 }; 01995 01996 template <class T> 01997 class FunctorTraits<functor::UnaryAnalyser<T> > 01998 : public FunctorTraitsBase<functor::UnaryAnalyser<T> > 01999 { 02000 public: 02001 typedef VigraTrueType isUnaryAnalyser; 02002 typedef VigraTrueType isBinaryAnalyser; 02003 typedef VigraTrueType isTernaryAnalyser; 02004 }; 02005 02006 02007 02008 } // namespace vigra 02009 02010 #endif /* NO_PARTIAL_TEMPLATE_SPECIALIZATION */ 02011 02012 #endif // DOXYGEN 02013 02014 #endif /* VIGRA_FUNCTOREXPRESSION_HXX */ 02015 02016
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|