1 // Boost operators.hpp header file ----------------------------------------// 2 3 // (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001. 4 // (C) Copyright Daniel Frey 2002-2016. 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 9 // See http://www.boost.org/libs/utility/operators.htm for documentation. 10 11 // Revision History 12 // 22 Feb 16 Added ADL protection, preserve old work-arounds in 13 // operators_v1.hpp and clean up this file. (Daniel Frey) 14 // 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++ 15 // (Matthew Bradbury, fixes #4432) 16 // 07 Aug 08 Added "euclidean" spelling. (Daniel Frey) 17 // 03 Apr 08 Make sure "convertible to bool" is sufficient 18 // for T::operator<, etc. (Daniel Frey) 19 // 24 May 07 Changed empty_base to depend on T, see 20 // http://svn.boost.org/trac/boost/ticket/979 21 // 21 Oct 02 Modified implementation of operators to allow compilers with a 22 // correct named return value optimization (NRVO) to produce optimal 23 // code. (Daniel Frey) 24 // 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel) 25 // 28 Sep 01 Factored out iterator operator groups. (Daryle Walker) 26 // 27 Aug 01 'left' form for non commutative operators added; 27 // additional classes for groups of related operators added; 28 // workaround for empty base class optimization 29 // bug of GCC 3.0 (Helmut Zeisel) 30 // 25 Jun 01 output_iterator_helper changes: removed default template 31 // parameters, added support for self-proxying, additional 32 // documentation and tests (Aleksey Gurtovoy) 33 // 29 May 01 Added operator classes for << and >>. Added input and output 34 // iterator helper classes. Added classes to connect equality and 35 // relational operators. Added classes for groups of related 36 // operators. Reimplemented example operator and iterator helper 37 // classes in terms of the new groups. (Daryle Walker, with help 38 // from Alexy Gurtovoy) 39 // 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly 40 // supplied arguments from actually being used (Dave Abrahams) 41 // 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and 42 // refactoring of compiler workarounds, additional documentation 43 // (Alexy Gurtovoy and Mark Rodgers with some help and prompting from 44 // Dave Abrahams) 45 // 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and 46 // Jeremy Siek (Dave Abrahams) 47 // 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 48 // (Mark Rodgers) 49 // 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) 50 // 10 Jun 00 Support for the base class chaining technique was added 51 // (Aleksey Gurtovoy). See documentation and the comments below 52 // for the details. 53 // 12 Dec 99 Initial version with iterator operators (Jeremy Siek) 54 // 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary 55 // specializations of dividable, subtractable, modable (Ed Brey) 56 // 17 Nov 99 Add comments (Beman Dawes) 57 // Remove unnecessary specialization of operators<> (Ed Brey) 58 // 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two 59 // operators.(Beman Dawes) 60 // 12 Nov 99 Add operators templates (Ed Brey) 61 // 11 Nov 99 Add single template parameter version for compilers without 62 // partial specialization (Beman Dawes) 63 // 10 Nov 99 Initial version 64 65 // 10 Jun 00: 66 // An additional optional template parameter was added to most of 67 // operator templates to support the base class chaining technique (see 68 // documentation for the details). Unfortunately, a straightforward 69 // implementation of this change would have broken compatibility with the 70 // previous version of the library by making it impossible to use the same 71 // template name (e.g. 'addable') for both the 1- and 2-argument versions of 72 // an operator template. This implementation solves the backward-compatibility 73 // issue at the cost of some simplicity. 74 // 75 // One of the complications is an existence of special auxiliary class template 76 // 'is_chained_base<>' (see 'operators_detail' namespace below), which is used 77 // to determine whether its template parameter is a library's operator template 78 // or not. You have to specialize 'is_chained_base<>' for each new 79 // operator template you add to the library. 80 // 81 // However, most of the non-trivial implementation details are hidden behind 82 // several local macros defined below, and as soon as you understand them, 83 // you understand the whole library implementation. 84 85 #ifndef BOOST_OPERATORS_HPP 86 #define BOOST_OPERATORS_HPP 87 88 // If old work-arounds are needed, refer to the preserved version without 89 // ADL protection. 90 #if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1) 91 #include "operators_v1.hpp" 92 #else 93 94 #include <cstddef> 95 #include <iterator> 96 97 #include <boost/config.hpp> 98 #include <boost/detail/workaround.hpp> 99 100 #if defined(__sgi) && !defined(__GNUC__) 101 # pragma set woff 1234 102 #endif 103 104 #if BOOST_WORKAROUND(BOOST_MSVC, < 1600) 105 # pragma warning( disable : 4284 ) // complaint about return type of 106 #endif // operator-> not begin a UDT 107 108 // In this section we supply the xxxx1 and xxxx2 forms of the operator 109 // templates, which are explicitly targeted at the 1-type-argument and 110 // 2-type-argument operator forms, respectively. 111 112 namespace boost 113 { 114 namespace operators_impl 115 { 116 namespace operators_detail 117 { 118 119 template <typename T> class empty_base {}; 120 121 } // namespace operators_detail 122 123 // Basic operator classes (contributed by Dave Abrahams) ------------------// 124 125 // Note that friend functions defined in a class are implicitly inline. 126 // See the C++ std, 11.4 [class.friend] paragraph 5 127 128 template <class T, class U, class B = operators_detail::empty_base<T> > 129 struct less_than_comparable2 : B 130 { operator <=(const T & x,const U & y)131 friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); } operator >=(const T & x,const U & y)132 friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); } operator >(const U & x,const T & y)133 friend bool operator>(const U& x, const T& y) { return y < x; } operator <(const U & x,const T & y)134 friend bool operator<(const U& x, const T& y) { return y > x; } operator <=(const U & x,const T & y)135 friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); } operator >=(const U & x,const T & y)136 friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); } 137 }; 138 139 template <class T, class B = operators_detail::empty_base<T> > 140 struct less_than_comparable1 : B 141 { operator >(const T & x,const T & y)142 friend bool operator>(const T& x, const T& y) { return y < x; } operator <=(const T & x,const T & y)143 friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); } operator >=(const T & x,const T & y)144 friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); } 145 }; 146 147 template <class T, class U, class B = operators_detail::empty_base<T> > 148 struct equality_comparable2 : B 149 { operator ==(const U & y,const T & x)150 friend bool operator==(const U& y, const T& x) { return x == y; } operator !=(const U & y,const T & x)151 friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); } operator !=(const T & y,const U & x)152 friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); } 153 }; 154 155 template <class T, class B = operators_detail::empty_base<T> > 156 struct equality_comparable1 : B 157 { operator !=(const T & x,const T & y)158 friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); } 159 }; 160 161 // A macro which produces "name_2left" from "name". 162 #define BOOST_OPERATOR2_LEFT(name) name##2##_##left 163 164 // NRVO-friendly implementation (contributed by Daniel Frey) ---------------// 165 166 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 167 168 // This is the optimal implementation for ISO/ANSI C++, 169 // but it requires the compiler to implement the NRVO. 170 // If the compiler has no NRVO, this is the best symmetric 171 // implementation available. 172 173 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 174 template <class T, class U, class B = operators_detail::empty_base<T> > \ 175 struct NAME##2 : B \ 176 { \ 177 friend T operator OP( const T& lhs, const U& rhs ) \ 178 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 179 friend T operator OP( const U& lhs, const T& rhs ) \ 180 { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ 181 }; \ 182 \ 183 template <class T, class B = operators_detail::empty_base<T> > \ 184 struct NAME##1 : B \ 185 { \ 186 friend T operator OP( const T& lhs, const T& rhs ) \ 187 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 188 }; 189 190 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 191 template <class T, class U, class B = operators_detail::empty_base<T> > \ 192 struct NAME##2 : B \ 193 { \ 194 friend T operator OP( const T& lhs, const U& rhs ) \ 195 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 196 }; \ 197 \ 198 template <class T, class U, class B = operators_detail::empty_base<T> > \ 199 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 200 { \ 201 friend T operator OP( const U& lhs, const T& rhs ) \ 202 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 203 }; \ 204 \ 205 template <class T, class B = operators_detail::empty_base<T> > \ 206 struct NAME##1 : B \ 207 { \ 208 friend T operator OP( const T& lhs, const T& rhs ) \ 209 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 210 }; 211 212 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 213 214 // For compilers without NRVO the following code is optimal, but not 215 // symmetric! Note that the implementation of 216 // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide 217 // optimization opportunities to the compiler :) 218 219 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 220 template <class T, class U, class B = operators_detail::empty_base<T> > \ 221 struct NAME##2 : B \ 222 { \ 223 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 224 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ 225 }; \ 226 \ 227 template <class T, class B = operators_detail::empty_base<T> > \ 228 struct NAME##1 : B \ 229 { \ 230 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 231 }; 232 233 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 234 template <class T, class U, class B = operators_detail::empty_base<T> > \ 235 struct NAME##2 : B \ 236 { \ 237 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 238 }; \ 239 \ 240 template <class T, class U, class B = operators_detail::empty_base<T> > \ 241 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 242 { \ 243 friend T operator OP( const U& lhs, const T& rhs ) \ 244 { return T( lhs ) OP##= rhs; } \ 245 }; \ 246 \ 247 template <class T, class B = operators_detail::empty_base<T> > \ 248 struct NAME##1 : B \ 249 { \ 250 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 251 }; 252 253 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 254 255 BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) 256 BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) 257 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) 258 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) 259 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) 260 BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) 261 BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) 262 BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) 263 264 #undef BOOST_BINARY_OPERATOR_COMMUTATIVE 265 #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE 266 #undef BOOST_OPERATOR2_LEFT 267 268 // incrementable and decrementable contributed by Jeremy Siek 269 270 template <class T, class B = operators_detail::empty_base<T> > 271 struct incrementable : B 272 { operator ++(T & x,int)273 friend T operator++(T& x, int) 274 { 275 incrementable_type nrv(x); 276 ++x; 277 return nrv; 278 } 279 private: // The use of this typedef works around a Borland bug 280 typedef T incrementable_type; 281 }; 282 283 template <class T, class B = operators_detail::empty_base<T> > 284 struct decrementable : B 285 { operator --(T & x,int)286 friend T operator--(T& x, int) 287 { 288 decrementable_type nrv(x); 289 --x; 290 return nrv; 291 } 292 private: // The use of this typedef works around a Borland bug 293 typedef T decrementable_type; 294 }; 295 296 // Iterator operator classes (contributed by Jeremy Siek) ------------------// 297 298 template <class T, class P, class B = operators_detail::empty_base<T> > 299 struct dereferenceable : B 300 { operator ->boost::operators_impl::dereferenceable301 P operator->() const 302 { 303 return &*static_cast<const T&>(*this); 304 } 305 }; 306 307 template <class T, class I, class R, class B = operators_detail::empty_base<T> > 308 struct indexable : B 309 { operator []boost::operators_impl::indexable310 R operator[](I n) const 311 { 312 return *(static_cast<const T&>(*this) + n); 313 } 314 }; 315 316 // More operator classes (contributed by Daryle Walker) --------------------// 317 // (NRVO-friendly implementation contributed by Daniel Frey) ---------------// 318 319 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 320 321 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 322 template <class T, class U, class B = operators_detail::empty_base<T> > \ 323 struct NAME##2 : B \ 324 { \ 325 friend T operator OP( const T& lhs, const U& rhs ) \ 326 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 327 }; \ 328 \ 329 template <class T, class B = operators_detail::empty_base<T> > \ 330 struct NAME##1 : B \ 331 { \ 332 friend T operator OP( const T& lhs, const T& rhs ) \ 333 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 334 }; 335 336 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 337 338 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 339 template <class T, class U, class B = operators_detail::empty_base<T> > \ 340 struct NAME##2 : B \ 341 { \ 342 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 343 }; \ 344 \ 345 template <class T, class B = operators_detail::empty_base<T> > \ 346 struct NAME##1 : B \ 347 { \ 348 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 349 }; 350 351 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 352 353 BOOST_BINARY_OPERATOR( left_shiftable, << ) 354 BOOST_BINARY_OPERATOR( right_shiftable, >> ) 355 356 #undef BOOST_BINARY_OPERATOR 357 358 template <class T, class U, class B = operators_detail::empty_base<T> > 359 struct equivalent2 : B 360 { operator ==(const T & x,const U & y)361 friend bool operator==(const T& x, const U& y) 362 { 363 return !static_cast<bool>(x < y) && !static_cast<bool>(x > y); 364 } 365 }; 366 367 template <class T, class B = operators_detail::empty_base<T> > 368 struct equivalent1 : B 369 { operator ==(const T & x,const T & y)370 friend bool operator==(const T&x, const T&y) 371 { 372 return !static_cast<bool>(x < y) && !static_cast<bool>(y < x); 373 } 374 }; 375 376 template <class T, class U, class B = operators_detail::empty_base<T> > 377 struct partially_ordered2 : B 378 { operator <=(const T & x,const U & y)379 friend bool operator<=(const T& x, const U& y) 380 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } operator >=(const T & x,const U & y)381 friend bool operator>=(const T& x, const U& y) 382 { return static_cast<bool>(x > y) || static_cast<bool>(x == y); } operator >(const U & x,const T & y)383 friend bool operator>(const U& x, const T& y) 384 { return y < x; } operator <(const U & x,const T & y)385 friend bool operator<(const U& x, const T& y) 386 { return y > x; } operator <=(const U & x,const T & y)387 friend bool operator<=(const U& x, const T& y) 388 { return static_cast<bool>(y > x) || static_cast<bool>(y == x); } operator >=(const U & x,const T & y)389 friend bool operator>=(const U& x, const T& y) 390 { return static_cast<bool>(y < x) || static_cast<bool>(y == x); } 391 }; 392 393 template <class T, class B = operators_detail::empty_base<T> > 394 struct partially_ordered1 : B 395 { operator >(const T & x,const T & y)396 friend bool operator>(const T& x, const T& y) 397 { return y < x; } operator <=(const T & x,const T & y)398 friend bool operator<=(const T& x, const T& y) 399 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } operator >=(const T & x,const T & y)400 friend bool operator>=(const T& x, const T& y) 401 { return static_cast<bool>(y < x) || static_cast<bool>(x == y); } 402 }; 403 404 // Combined operator classes (contributed by Daryle Walker) ----------------// 405 406 template <class T, class U, class B = operators_detail::empty_base<T> > 407 struct totally_ordered2 408 : less_than_comparable2<T, U 409 , equality_comparable2<T, U, B 410 > > {}; 411 412 template <class T, class B = operators_detail::empty_base<T> > 413 struct totally_ordered1 414 : less_than_comparable1<T 415 , equality_comparable1<T, B 416 > > {}; 417 418 template <class T, class U, class B = operators_detail::empty_base<T> > 419 struct additive2 420 : addable2<T, U 421 , subtractable2<T, U, B 422 > > {}; 423 424 template <class T, class B = operators_detail::empty_base<T> > 425 struct additive1 426 : addable1<T 427 , subtractable1<T, B 428 > > {}; 429 430 template <class T, class U, class B = operators_detail::empty_base<T> > 431 struct multiplicative2 432 : multipliable2<T, U 433 , dividable2<T, U, B 434 > > {}; 435 436 template <class T, class B = operators_detail::empty_base<T> > 437 struct multiplicative1 438 : multipliable1<T 439 , dividable1<T, B 440 > > {}; 441 442 template <class T, class U, class B = operators_detail::empty_base<T> > 443 struct integer_multiplicative2 444 : multiplicative2<T, U 445 , modable2<T, U, B 446 > > {}; 447 448 template <class T, class B = operators_detail::empty_base<T> > 449 struct integer_multiplicative1 450 : multiplicative1<T 451 , modable1<T, B 452 > > {}; 453 454 template <class T, class U, class B = operators_detail::empty_base<T> > 455 struct arithmetic2 456 : additive2<T, U 457 , multiplicative2<T, U, B 458 > > {}; 459 460 template <class T, class B = operators_detail::empty_base<T> > 461 struct arithmetic1 462 : additive1<T 463 , multiplicative1<T, B 464 > > {}; 465 466 template <class T, class U, class B = operators_detail::empty_base<T> > 467 struct integer_arithmetic2 468 : additive2<T, U 469 , integer_multiplicative2<T, U, B 470 > > {}; 471 472 template <class T, class B = operators_detail::empty_base<T> > 473 struct integer_arithmetic1 474 : additive1<T 475 , integer_multiplicative1<T, B 476 > > {}; 477 478 template <class T, class U, class B = operators_detail::empty_base<T> > 479 struct bitwise2 480 : xorable2<T, U 481 , andable2<T, U 482 , orable2<T, U, B 483 > > > {}; 484 485 template <class T, class B = operators_detail::empty_base<T> > 486 struct bitwise1 487 : xorable1<T 488 , andable1<T 489 , orable1<T, B 490 > > > {}; 491 492 template <class T, class B = operators_detail::empty_base<T> > 493 struct unit_steppable 494 : incrementable<T 495 , decrementable<T, B 496 > > {}; 497 498 template <class T, class U, class B = operators_detail::empty_base<T> > 499 struct shiftable2 500 : left_shiftable2<T, U 501 , right_shiftable2<T, U, B 502 > > {}; 503 504 template <class T, class B = operators_detail::empty_base<T> > 505 struct shiftable1 506 : left_shiftable1<T 507 , right_shiftable1<T, B 508 > > {}; 509 510 template <class T, class U, class B = operators_detail::empty_base<T> > 511 struct ring_operators2 512 : additive2<T, U 513 , subtractable2_left<T, U 514 , multipliable2<T, U, B 515 > > > {}; 516 517 template <class T, class B = operators_detail::empty_base<T> > 518 struct ring_operators1 519 : additive1<T 520 , multipliable1<T, B 521 > > {}; 522 523 template <class T, class U, class B = operators_detail::empty_base<T> > 524 struct ordered_ring_operators2 525 : ring_operators2<T, U 526 , totally_ordered2<T, U, B 527 > > {}; 528 529 template <class T, class B = operators_detail::empty_base<T> > 530 struct ordered_ring_operators1 531 : ring_operators1<T 532 , totally_ordered1<T, B 533 > > {}; 534 535 template <class T, class U, class B = operators_detail::empty_base<T> > 536 struct field_operators2 537 : ring_operators2<T, U 538 , dividable2<T, U 539 , dividable2_left<T, U, B 540 > > > {}; 541 542 template <class T, class B = operators_detail::empty_base<T> > 543 struct field_operators1 544 : ring_operators1<T 545 , dividable1<T, B 546 > > {}; 547 548 template <class T, class U, class B = operators_detail::empty_base<T> > 549 struct ordered_field_operators2 550 : field_operators2<T, U 551 , totally_ordered2<T, U, B 552 > > {}; 553 554 template <class T, class B = operators_detail::empty_base<T> > 555 struct ordered_field_operators1 556 : field_operators1<T 557 , totally_ordered1<T, B 558 > > {}; 559 560 template <class T, class U, class B = operators_detail::empty_base<T> > 561 struct euclidian_ring_operators2 562 : ring_operators2<T, U 563 , dividable2<T, U 564 , dividable2_left<T, U 565 , modable2<T, U 566 , modable2_left<T, U, B 567 > > > > > {}; 568 569 template <class T, class B = operators_detail::empty_base<T> > 570 struct euclidian_ring_operators1 571 : ring_operators1<T 572 , dividable1<T 573 , modable1<T, B 574 > > > {}; 575 576 template <class T, class U, class B = operators_detail::empty_base<T> > 577 struct ordered_euclidian_ring_operators2 578 : totally_ordered2<T, U 579 , euclidian_ring_operators2<T, U, B 580 > > {}; 581 582 template <class T, class B = operators_detail::empty_base<T> > 583 struct ordered_euclidian_ring_operators1 584 : totally_ordered1<T 585 , euclidian_ring_operators1<T, B 586 > > {}; 587 588 template <class T, class U, class B = operators_detail::empty_base<T> > 589 struct euclidean_ring_operators2 590 : ring_operators2<T, U 591 , dividable2<T, U 592 , dividable2_left<T, U 593 , modable2<T, U 594 , modable2_left<T, U, B 595 > > > > > {}; 596 597 template <class T, class B = operators_detail::empty_base<T> > 598 struct euclidean_ring_operators1 599 : ring_operators1<T 600 , dividable1<T 601 , modable1<T, B 602 > > > {}; 603 604 template <class T, class U, class B = operators_detail::empty_base<T> > 605 struct ordered_euclidean_ring_operators2 606 : totally_ordered2<T, U 607 , euclidean_ring_operators2<T, U, B 608 > > {}; 609 610 template <class T, class B = operators_detail::empty_base<T> > 611 struct ordered_euclidean_ring_operators1 612 : totally_ordered1<T 613 , euclidean_ring_operators1<T, B 614 > > {}; 615 616 template <class T, class P, class B = operators_detail::empty_base<T> > 617 struct input_iteratable 618 : equality_comparable1<T 619 , incrementable<T 620 , dereferenceable<T, P, B 621 > > > {}; 622 623 template <class T, class B = operators_detail::empty_base<T> > 624 struct output_iteratable 625 : incrementable<T, B 626 > {}; 627 628 template <class T, class P, class B = operators_detail::empty_base<T> > 629 struct forward_iteratable 630 : input_iteratable<T, P, B 631 > {}; 632 633 template <class T, class P, class B = operators_detail::empty_base<T> > 634 struct bidirectional_iteratable 635 : forward_iteratable<T, P 636 , decrementable<T, B 637 > > {}; 638 639 // To avoid repeated derivation from equality_comparable, 640 // which is an indirect base class of bidirectional_iterable, 641 // random_access_iteratable must not be derived from totally_ordered1 642 // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) 643 template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> > 644 struct random_access_iteratable 645 : bidirectional_iteratable<T, P 646 , less_than_comparable1<T 647 , additive2<T, D 648 , indexable<T, D, R, B 649 > > > > {}; 650 651 652 // 653 // Here's where we put it all together, defining the xxxx forms of the templates. 654 // We also define specializations of is_chained_base<> for 655 // the xxxx, xxxx1, and xxxx2 templates. 656 // 657 658 namespace operators_detail 659 { 660 661 // A type parameter is used instead of a plain bool because Borland's compiler 662 // didn't cope well with the more obvious non-type template parameter. 663 struct true_t {}; 664 struct false_t {}; 665 666 } // namespace operators_detail 667 668 // is_chained_base<> - a traits class used to distinguish whether an operator 669 // template argument is being used for base class chaining, or is specifying a 670 // 2nd argument type. 671 672 // Unspecialized version assumes that most types are not being used for base 673 // class chaining. We specialize for the operator templates defined in this 674 // library. 675 template<class T> struct is_chained_base { 676 typedef operators_detail::false_t value; 677 }; 678 679 // Provide a specialization of 'is_chained_base<>' 680 // for a 4-type-argument operator template. 681 # define BOOST_OPERATOR_TEMPLATE4(template_name4) \ 682 template<class T, class U, class V, class W, class B> \ 683 struct is_chained_base< template_name4<T, U, V, W, B> > { \ 684 typedef operators_detail::true_t value; \ 685 }; 686 687 // Provide a specialization of 'is_chained_base<>' 688 // for a 3-type-argument operator template. 689 # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ 690 template<class T, class U, class V, class B> \ 691 struct is_chained_base< template_name3<T, U, V, B> > { \ 692 typedef operators_detail::true_t value; \ 693 }; 694 695 // Provide a specialization of 'is_chained_base<>' 696 // for a 2-type-argument operator template. 697 # define BOOST_OPERATOR_TEMPLATE2(template_name2) \ 698 template<class T, class U, class B> \ 699 struct is_chained_base< template_name2<T, U, B> > { \ 700 typedef operators_detail::true_t value; \ 701 }; 702 703 // Provide a specialization of 'is_chained_base<>' 704 // for a 1-type-argument operator template. 705 # define BOOST_OPERATOR_TEMPLATE1(template_name1) \ 706 template<class T, class B> \ 707 struct is_chained_base< template_name1<T, B> > { \ 708 typedef operators_detail::true_t value; \ 709 }; 710 711 // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it 712 // can be used for specifying both 1-argument and 2-argument forms. Requires the 713 // existence of two previously defined class templates named '<template_name>1' 714 // and '<template_name>2' which must implement the corresponding 1- and 2- 715 // argument forms. 716 // 717 // The template type parameter O == is_chained_base<U>::value is used to 718 // distinguish whether the 2nd argument to <template_name> is being used for 719 // base class chaining from another boost operator template or is describing a 720 // 2nd operand type. O == true_t only when U is actually an another operator 721 // template from the library. Partial specialization is used to select an 722 // implementation in terms of either '<template_name>1' or '<template_name>2'. 723 // 724 725 # define BOOST_OPERATOR_TEMPLATE(template_name) \ 726 template <class T \ 727 ,class U = T \ 728 ,class B = operators_detail::empty_base<T> \ 729 ,class O = typename is_chained_base<U>::value \ 730 > \ 731 struct template_name; \ 732 \ 733 template<class T, class U, class B> \ 734 struct template_name<T, U, B, operators_detail::false_t> \ 735 : template_name##2<T, U, B> {}; \ 736 \ 737 template<class T, class U> \ 738 struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \ 739 : template_name##1<T, U> {}; \ 740 \ 741 template <class T, class B> \ 742 struct template_name<T, T, B, operators_detail::false_t> \ 743 : template_name##1<T, B> {}; \ 744 \ 745 template<class T, class U, class B, class O> \ 746 struct is_chained_base< template_name<T, U, B, O> > { \ 747 typedef operators_detail::true_t value; \ 748 }; \ 749 \ 750 BOOST_OPERATOR_TEMPLATE2(template_name##2) \ 751 BOOST_OPERATOR_TEMPLATE1(template_name##1) 752 753 BOOST_OPERATOR_TEMPLATE(less_than_comparable) 754 BOOST_OPERATOR_TEMPLATE(equality_comparable) 755 BOOST_OPERATOR_TEMPLATE(multipliable) 756 BOOST_OPERATOR_TEMPLATE(addable) 757 BOOST_OPERATOR_TEMPLATE(subtractable) 758 BOOST_OPERATOR_TEMPLATE2(subtractable2_left) 759 BOOST_OPERATOR_TEMPLATE(dividable) 760 BOOST_OPERATOR_TEMPLATE2(dividable2_left) 761 BOOST_OPERATOR_TEMPLATE(modable) 762 BOOST_OPERATOR_TEMPLATE2(modable2_left) 763 BOOST_OPERATOR_TEMPLATE(xorable) 764 BOOST_OPERATOR_TEMPLATE(andable) 765 BOOST_OPERATOR_TEMPLATE(orable) 766 767 BOOST_OPERATOR_TEMPLATE1(incrementable) 768 BOOST_OPERATOR_TEMPLATE1(decrementable) 769 770 BOOST_OPERATOR_TEMPLATE2(dereferenceable) 771 BOOST_OPERATOR_TEMPLATE3(indexable) 772 773 BOOST_OPERATOR_TEMPLATE(left_shiftable) 774 BOOST_OPERATOR_TEMPLATE(right_shiftable) 775 BOOST_OPERATOR_TEMPLATE(equivalent) 776 BOOST_OPERATOR_TEMPLATE(partially_ordered) 777 778 BOOST_OPERATOR_TEMPLATE(totally_ordered) 779 BOOST_OPERATOR_TEMPLATE(additive) 780 BOOST_OPERATOR_TEMPLATE(multiplicative) 781 BOOST_OPERATOR_TEMPLATE(integer_multiplicative) 782 BOOST_OPERATOR_TEMPLATE(arithmetic) 783 BOOST_OPERATOR_TEMPLATE(integer_arithmetic) 784 BOOST_OPERATOR_TEMPLATE(bitwise) 785 BOOST_OPERATOR_TEMPLATE1(unit_steppable) 786 BOOST_OPERATOR_TEMPLATE(shiftable) 787 BOOST_OPERATOR_TEMPLATE(ring_operators) 788 BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) 789 BOOST_OPERATOR_TEMPLATE(field_operators) 790 BOOST_OPERATOR_TEMPLATE(ordered_field_operators) 791 BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) 792 BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) 793 BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) 794 BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) 795 BOOST_OPERATOR_TEMPLATE2(input_iteratable) 796 BOOST_OPERATOR_TEMPLATE1(output_iteratable) 797 BOOST_OPERATOR_TEMPLATE2(forward_iteratable) 798 BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) 799 BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) 800 801 #undef BOOST_OPERATOR_TEMPLATE 802 #undef BOOST_OPERATOR_TEMPLATE4 803 #undef BOOST_OPERATOR_TEMPLATE3 804 #undef BOOST_OPERATOR_TEMPLATE2 805 #undef BOOST_OPERATOR_TEMPLATE1 806 807 template <class T, class U> 808 struct operators2 809 : totally_ordered2<T,U 810 , integer_arithmetic2<T,U 811 , bitwise2<T,U 812 > > > {}; 813 814 template <class T, class U = T> 815 struct operators : operators2<T, U> {}; 816 817 template <class T> struct operators<T, T> 818 : totally_ordered<T 819 , integer_arithmetic<T 820 , bitwise<T 821 , unit_steppable<T 822 > > > > {}; 823 824 // Iterator helper classes (contributed by Jeremy Siek) -------------------// 825 // (Input and output iterator helpers contributed by Daryle Walker) -------// 826 // (Changed to use combined operator classes by Daryle Walker) ------------// 827 template <class T, 828 class V, 829 class D = std::ptrdiff_t, 830 class P = V const *, 831 class R = V const &> 832 struct input_iterator_helper 833 : input_iteratable<T, P 834 , std::iterator<std::input_iterator_tag, V, D, P, R 835 > > {}; 836 837 template<class T> 838 struct output_iterator_helper 839 : output_iteratable<T 840 , std::iterator<std::output_iterator_tag, void, void, void, void 841 > > 842 { operator *boost::operators_impl::output_iterator_helper843 T& operator*() { return static_cast<T&>(*this); } operator ++boost::operators_impl::output_iterator_helper844 T& operator++() { return static_cast<T&>(*this); } 845 }; 846 847 template <class T, 848 class V, 849 class D = std::ptrdiff_t, 850 class P = V*, 851 class R = V&> 852 struct forward_iterator_helper 853 : forward_iteratable<T, P 854 , std::iterator<std::forward_iterator_tag, V, D, P, R 855 > > {}; 856 857 template <class T, 858 class V, 859 class D = std::ptrdiff_t, 860 class P = V*, 861 class R = V&> 862 struct bidirectional_iterator_helper 863 : bidirectional_iteratable<T, P 864 , std::iterator<std::bidirectional_iterator_tag, V, D, P, R 865 > > {}; 866 867 template <class T, 868 class V, 869 class D = std::ptrdiff_t, 870 class P = V*, 871 class R = V&> 872 struct random_access_iterator_helper 873 : random_access_iteratable<T, P, D, R 874 , std::iterator<std::random_access_iterator_tag, V, D, P, R 875 > > 876 { requires_difference_operator(const T & x,const T & y)877 friend D requires_difference_operator(const T& x, const T& y) { 878 return x - y; 879 } 880 }; // random_access_iterator_helper 881 882 } // namespace operators_impl 883 using namespace operators_impl; 884 885 } // namespace boost 886 887 #if defined(__sgi) && !defined(__GNUC__) 888 #pragma reset woff 1234 889 #endif 890 891 #endif // BOOST_NO_OPERATORS_IN_NAMESPACE 892 #endif // BOOST_OPERATORS_HPP 893