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