Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development 00002 // Laboratory (LRDE) 00003 // 00004 // This file is part of Olena. 00005 // 00006 // Olena is free software: you can redistribute it and/or modify it under 00007 // the terms of the GNU General Public License as published by the Free 00008 // Software Foundation, version 2 of the License. 00009 // 00010 // Olena is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software project without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to produce 00022 // an executable, this file does not by itself cause the resulting 00023 // executable to be covered by the GNU General Public License. This 00024 // exception does not however invalidate any other reasons why the 00025 // executable file might be covered by the GNU General Public License. 00026 00027 #ifndef MLN_CORE_ROUTINE_OPS_HH 00028 # define MLN_CORE_ROUTINE_OPS_HH 00029 00033 00092 # include <mln/trait/op/all.hh> 00093 # include <mln/core/concept/object.hh> 00094 # include <mln/metal/converts_to.hh> 00095 00096 00097 namespace mln 00098 { 00099 00100 // Fwd decls. 00101 namespace literal { struct zero_t; struct one_t; } 00102 00103 00104 namespace trait 00105 { 00106 00107 // For unary operators. 00108 00109 00111 template <typename O> 00112 struct set_unary_< op::uplus, Object,O > { typedef O ret; }; 00113 00115 template <typename O> 00116 struct set_unary_< op::uminus, Object,O > { typedef mln_trait_op_minus(O, O) ret; }; 00117 00119 template <typename O> 00120 struct set_unary_< op::preinc, Object,O > { typedef O& ret; }; 00121 00123 template <typename O> 00124 struct set_unary_< op::predec, Object,O > { typedef O& ret; }; 00125 00127 template <typename O> 00128 struct set_unary_< op::postinc, Object,O > { typedef O ret; }; 00129 00131 template <typename O> 00132 struct set_unary_< op::postdec, Object,O > { typedef O ret; }; 00133 00134 00135 00136 // For binary operators. 00137 00138 template <typename O1, typename O2> 00139 struct set_binary_< op::eq, Object,O1, Object,O2 > { typedef bool ret; }; 00140 00141 template <typename O1, typename O2> 00142 struct set_binary_< op::neq, Object,O1, Object,O2 > 00143 { 00144 // O1 != O2 --> ! (O1 == O2) 00145 typedef mln_trait_op_eq(O1, O2) B_; 00146 typedef mln_trait_op_not(B_) ret; 00147 }; 00148 00149 template <typename O1, typename O2> 00150 struct set_binary_< op::less, Object,O1, Object,O2 > { typedef bool ret; }; 00151 00152 template <typename O1, typename O2> 00153 struct set_binary_< op::leq, Object,O1, Object,O2 > 00154 { 00155 // O1 <= O2 --> ! (O2 < 01) 00156 typedef mln_trait_op_less(O2, O1) B_; 00157 typedef mln_trait_op_not(B_) ret; 00158 }; 00159 00160 template <typename O1, typename O2> 00161 struct set_binary_< op::geq, Object,O1, Object,O2 > 00162 { 00163 // O1 >= O2 --> O2 <= O1 00164 typedef mln_trait_op_leq(O2, O1) ret; 00165 }; 00166 00167 template <typename O1, typename O2> 00168 struct set_binary_< op::greater, Object,O1, Object,O2 > 00169 { 00170 // O1 > O2 --> O2 < O1 00171 typedef mln_trait_op_less(O2, O1) ret; 00172 }; 00173 00174 // FIXME: Same for the other definitions below... 00175 00176 00177 00178 // Case of "const" in types. 00179 00180 template< template <class> class Name, 00181 typename O > 00182 struct set_precise_unary_< Name, const O > 00183 { 00184 typedef mln_trait_unary(Name, O) ret; 00185 }; 00186 00187 template< template <class,class> class Name, 00188 typename O1, typename O2 > 00189 struct set_precise_binary_< Name, O1, const O2 > 00190 { 00191 typedef mln_trait_binary(Name, O1, O2) ret; 00192 }; 00193 00194 template< template <class,class> class Name, 00195 typename O1, typename O2 > 00196 struct set_precise_binary_< Name, const O1, O2 > 00197 { 00198 typedef mln_trait_binary(Name, O1, O2) ret; 00199 }; 00200 00201 template< template <class,class> class Name, 00202 typename O1, typename O2 > 00203 struct set_precise_binary_< Name, const O1, const O2 > 00204 { 00205 typedef mln_trait_binary(Name, O1, O2) ret; 00206 }; 00207 00208 00209 } // end of mln::trait 00210 00211 00212 00222 template <typename O1, typename O2> 00223 mln_trait_op_neq(O1, O2) 00224 operator!=(const Object<O1>& lhs, const Object<O2>& rhs); 00225 00226 00236 template <typename O1, typename O2> 00237 mln_trait_op_greater(O1, O2) 00238 operator>(const Object<O1>& lhs, const Object<O2>& rhs); 00239 00240 00251 template <typename O1, typename O2> 00252 mln_trait_op_geq(O1, O2) 00253 operator>=(const Object<O1>& lhs, const Object<O2>& rhs); 00254 00255 00266 template <typename O1, typename O2> 00267 mln_trait_op_leq(O1, O2) 00268 operator<=(const Object<O1>& lhs, const Object<O2>& rhs); 00269 00270 00271 /* \brief Default definition of the post-incrementation operator. 00272 * 00273 * It relies on the definition of the pre-incrementation operator. 00274 */ 00275 template <typename O> 00276 O operator++(Object<O>& lhs, int); 00277 00278 00279 /* \brief Default definition of the post-decrementation operator. 00280 * 00281 * It relies on the definition of the pre-decrementation operator. 00282 */ 00283 template <typename O> 00284 O operator--(Object<O>& lhs, int); 00285 00286 00287 /* \brief Default definition of the pre-incrementation operator. 00288 * 00289 * It relies on "+ literal::one". 00290 */ 00291 template <typename O> 00292 O& operator++(Object<O>& rhs); 00293 00294 00295 /* \brief Default definition of the pre-decrementation operator. 00296 * 00297 * It relies on "- literal::one". 00298 */ 00299 template <typename O> 00300 O& operator--(Object<O>& rhs); 00301 00302 00303 /* \brief Default definitions of the "unary plus" operator. 00304 * 00305 * \param[in] rhs An object 00306 * \return A copy of \p rhs. 00307 */ 00308 template <typename O> 00309 O operator+(const Object<O>& rhs); 00310 00311 00312 /* \brief Default definition of the "unary minus" operator. 00313 * 00314 * \param[in] rhs An object 00315 * \return 0 - \p rhs. 00316 * 00317 * It relies on "O(literal::zero) - rhs". 00318 */ 00319 template <typename O> 00320 mln_trait_op_minus(O, O) 00321 operator-(const Object<O>& rhs); 00322 00323 00324 /* \brief Default definition of the "plus equal" operator. 00325 * 00326 * \param[in,out] lhs The target object. 00327 * \param[in] rhs The auxiliary object. 00328 * \return The target object \p lhs once modified. 00329 * 00330 * It relies on "lhs = L(lhs) + rhs". 00331 */ 00332 template <typename L, typename R> 00333 L& 00334 operator+=(Object<L>& lhs, const Object<R>& rhs); 00335 00336 00337 /* \brief Default definition of the "minus equal" operator. 00338 * 00339 * \param[in,out] lhs The target object. 00340 * \param[in] rhs The auxiliary object. 00341 * \return The target object \p lhs once modified. 00342 * 00343 * It relies on "lhs = L(lhs) - rhs". 00344 */ 00345 template <typename L, typename R> 00346 L& 00347 operator-=(Object<L>& lhs, const Object<R>& rhs); 00348 00349 00350 /* \brief Default definition of the "times equal" operator. 00351 * 00352 * \param[in,out] lhs The target object. 00353 * \param[in] rhs The auxiliary object. 00354 * \return The target object \p lhs once modified. 00355 * 00356 * It relies on "lhs = L(lhs) * rhs". 00357 */ 00358 template <typename L, typename R> 00359 L& 00360 operator*=(Object<L>& lhs, const Object<R>& rhs); 00361 00362 00363 /* \brief Default definition of the "div equal" operator. 00364 * 00365 * \param[in,out] lhs The target object. 00366 * \param[in] rhs The auxiliary object. 00367 * \return The target object \p lhs once modified. 00368 * 00369 * It relies on "lhs = L(lhs) / rhs". 00370 */ 00371 template <typename L, typename R> 00372 L& 00373 operator/=(Object<L>& lhs, const Object<R>& rhs); 00374 00375 00376 /* \brief Default definition of the "mod equal" operator. 00377 * 00378 * \param[in,out] lhs The target object. 00379 * \param[in] rhs The auxiliary object. 00380 * \return The target object \p lhs once modified. 00381 * 00382 * It relies on "lhs = L(lhs) % rhs". 00383 */ 00384 template <typename L, typename R> 00385 L& 00386 operator%=(Object<L>& lhs, const Object<R>& rhs); 00387 00388 00389 00390 # ifndef MLN_INCLUDE_ONLY 00391 00392 // Plus equal. 00393 00394 template <typename L, typename R> 00395 inline 00396 L& 00397 operator+=(Object<L>& lhs, const Object<R>& rhs) 00398 { 00399 typedef mln_trait_op_plus(L, R) P; 00400 mlc_converts_to(P, L)::check(); 00401 return exact(lhs) = static_cast<L>(exact(lhs) + exact(rhs)); 00402 } 00403 00404 // Minus equal. 00405 00406 template <typename L, typename R> 00407 inline 00408 L& 00409 operator-=(Object<L>& lhs, const Object<R>& rhs) 00410 { 00411 typedef mln_trait_op_minus(L, R) M; 00412 mlc_converts_to(M, L)::check(); 00413 return exact(lhs) = static_cast<L>(exact(lhs) - exact(rhs)); 00414 } 00415 00416 // Times equal. 00417 00418 template <typename L, typename R> 00419 inline 00420 L& 00421 operator*=(Object<L>& lhs, const Object<R>& rhs) 00422 { 00423 typedef mln_trait_op_times(L, R) T; 00424 mlc_converts_to(T, L)::check(); 00425 return exact(lhs) = static_cast<L>(exact(lhs) * exact(rhs)); 00426 } 00427 00428 // Div equal. 00429 00430 template <typename L, typename R> 00431 inline 00432 L& 00433 operator/=(Object<L>& lhs, const Object<R>& rhs) 00434 { 00435 typedef mln_trait_op_div(L, R) D; 00436 mlc_converts_to(D, L)::check(); 00437 // Remark: 00438 // The code below gives a warning with g++-3.3 with the test file 00439 // tests/value/int_u8.cc. It is normal since writing "i /= f" 00440 // means casting eventually float to int. Yet what do we want in 00441 // that case? A quiet compilation or a warning? 00442 return exact(lhs) = static_cast<L>(exact(lhs) / exact(rhs)); 00443 } 00444 00445 // Mod equal. 00446 00447 template <typename L, typename R> 00448 inline 00449 L& 00450 operator%=(Object<L>& lhs, const Object<R>& rhs) 00451 { 00452 typedef mln_trait_op_mod(L, R) M; 00453 mlc_converts_to(M, L)::check(); 00454 return exact(lhs) = static_cast<L>(exact(lhs) % exact(rhs)); 00455 } 00456 00457 // Unary plus. 00458 00459 template <typename O> 00460 inline 00461 O 00462 operator+(const Object<O>& rhs) 00463 { 00464 return exact(rhs); // Cpy. 00465 } 00466 00467 // Unary minus. 00468 00469 template <typename O> 00470 inline 00471 mln_trait_op_minus(O, O) 00472 operator-(const Object<O>& rhs) 00473 { 00474 mlc_converts_to(literal::zero_t, O)::check(); 00475 literal::zero_t* p_zero = 0; 00476 return O(*p_zero) - exact(rhs); 00477 } 00478 00479 // Post-incrementation. 00480 00481 template <typename O> 00482 inline 00483 O 00484 operator++(Object<O>& lhs, int) 00485 { 00486 O tmp(exact(lhs)); // Copy. 00487 ++exact(lhs); // Pre-inc. 00488 // FIXME: Activate: mln_postcondition(exact(lhs) == tmp + literal::one); 00489 return tmp; 00490 } 00491 00492 // Post-decrementation. 00493 00494 template <typename O> 00495 inline 00496 O 00497 operator--(Object<O>& lhs, int) 00498 { 00499 O tmp(exact(lhs)); // Copy. 00500 --exact(lhs); // Pre-dec. 00501 // FIXME: Activate: mln_postcondition(exact(lhs) == tmp - literal::one); 00502 return tmp; 00503 } 00504 00505 // Pre-decrementation. 00506 00507 template <typename O> 00508 inline 00509 O& 00510 operator--(Object<O>& rhs) 00511 { 00512 literal::one_t* p_one; 00513 exact(rhs) -= *p_one; 00514 return exact(rhs); 00515 } 00516 00517 // Pre-incrementation. 00518 00519 template <typename O> 00520 inline 00521 O& 00522 operator++(Object<O>& rhs) 00523 { 00524 literal::one_t* p_one; 00525 exact(rhs) += *p_one; 00526 return exact(rhs); 00527 } 00528 00529 // Comparisons. 00530 00531 template <typename O1, typename O2> 00532 inline 00533 mln_trait_op_neq(O1, O2) 00534 operator!=(const Object<O1>& lhs, const Object<O2>& rhs) 00535 { 00536 return ! (exact(lhs) == exact(rhs)); 00537 } 00538 00539 template <typename O1, typename O2> 00540 inline 00541 mln_trait_op_greater(O1, O2) 00542 operator>(const Object<O1>& lhs, const Object<O2>& rhs) 00543 { 00544 return exact(rhs) < exact(lhs); 00545 } 00546 00547 template <typename O1, typename O2> 00548 inline 00549 mln_trait_op_geq(O1, O2) 00550 operator>=(const Object<O1>& lhs, const Object<O2>& rhs) 00551 { 00552 return exact(rhs) <= exact(lhs); 00553 } 00554 00555 template <typename O1, typename O2> 00556 inline 00557 mln_trait_op_leq(O1, O2) 00558 operator<=(const Object<O1>& lhs, const Object<O2>& rhs) 00559 { 00560 // if partial ordering, this operator should be re-defined! 00561 return ! (exact(rhs) < exact(lhs)); 00562 } 00563 00564 # endif // ! MLN_INCLUDE_ONLY 00565 00566 } // end of namespace mln 00567 00568 00569 #endif // ! MLN_CORE_ROUTINE_OPS_HH