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 // Define BOOST_OPERATORS_CONSTEXPR to be like BOOST_CONSTEXPR but empty under MSVC < v19.22 113 #if BOOST_WORKAROUND(BOOST_MSVC, < 1922) 114 #define BOOST_OPERATORS_CONSTEXPR 115 #else 116 #define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR 117 #endif 118 119 // In this section we supply the xxxx1 and xxxx2 forms of the operator 120 // templates, which are explicitly targeted at the 1-type-argument and 121 // 2-type-argument operator forms, respectively. 122 123 namespace boost 124 { 125 namespace operators_impl 126 { 127 namespace operators_detail 128 { 129 130 template <typename T> class empty_base {}; 131 132 } // namespace operators_detail 133 134 // Basic operator classes (contributed by Dave Abrahams) ------------------// 135 136 // Note that friend functions defined in a class are implicitly inline. 137 // See the C++ std, 11.4 [class.friend] paragraph 5 138 139 template <class T, class U, class B = operators_detail::empty_base<T> > 140 struct less_than_comparable2 : B 141 { operator <=(const T & x,const U & y)142 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); } operator >=(const T & x,const U & y)143 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); } operator >(const U & x,const T & y)144 friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } operator <(const U & x,const T & y)145 friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } operator <=(const U & x,const T & y)146 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); } operator >=(const U & x,const T & y)147 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); } 148 }; 149 150 template <class T, class B = operators_detail::empty_base<T> > 151 struct less_than_comparable1 : B 152 { operator >(const T & x,const T & y)153 friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } operator <=(const T & x,const T & y)154 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); } operator >=(const T & x,const T & y)155 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); } 156 }; 157 158 template <class T, class U, class B = operators_detail::empty_base<T> > 159 struct equality_comparable2 : B 160 { operator ==(const U & y,const T & x)161 friend BOOST_OPERATORS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; } operator !=(const U & y,const T & x)162 friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); } operator !=(const T & y,const U & x)163 friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); } 164 }; 165 166 template <class T, class B = operators_detail::empty_base<T> > 167 struct equality_comparable1 : B 168 { operator !=(const T & x,const T & y)169 friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); } 170 }; 171 172 // A macro which produces "name_2left" from "name". 173 #define BOOST_OPERATOR2_LEFT(name) name##2##_##left 174 175 // NRVO-friendly implementation (contributed by Daniel Frey) ---------------// 176 177 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 178 179 // This is the optimal implementation for ISO/ANSI C++, 180 // but it requires the compiler to implement the NRVO. 181 // If the compiler has no NRVO, this is the best symmetric 182 // implementation available. 183 184 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 185 template <class T, class U, class B = operators_detail::empty_base<T> > \ 186 struct NAME##2 : B \ 187 { \ 188 friend T operator OP( const T& lhs, const U& rhs ) \ 189 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 190 friend T operator OP( const U& lhs, const T& rhs ) \ 191 { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ 192 }; \ 193 \ 194 template <class T, class B = operators_detail::empty_base<T> > \ 195 struct NAME##1 : B \ 196 { \ 197 friend T operator OP( const T& lhs, const T& rhs ) \ 198 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 199 }; 200 201 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 202 template <class T, class U, class B = operators_detail::empty_base<T> > \ 203 struct NAME##2 : B \ 204 { \ 205 friend T operator OP( const T& lhs, const U& rhs ) \ 206 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 207 }; \ 208 \ 209 template <class T, class U, class B = operators_detail::empty_base<T> > \ 210 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 211 { \ 212 friend T operator OP( const U& lhs, const T& rhs ) \ 213 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 214 }; \ 215 \ 216 template <class T, class B = operators_detail::empty_base<T> > \ 217 struct NAME##1 : B \ 218 { \ 219 friend T operator OP( const T& lhs, const T& rhs ) \ 220 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 221 }; 222 223 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 224 225 // For compilers without NRVO the following code is optimal, but not 226 // symmetric! Note that the implementation of 227 // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide 228 // optimization opportunities to the compiler :) 229 230 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 231 template <class T, class U, class B = operators_detail::empty_base<T> > \ 232 struct NAME##2 : B \ 233 { \ 234 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 235 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ 236 }; \ 237 \ 238 template <class T, class B = operators_detail::empty_base<T> > \ 239 struct NAME##1 : B \ 240 { \ 241 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 242 }; 243 244 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 245 template <class T, class U, class B = operators_detail::empty_base<T> > \ 246 struct NAME##2 : B \ 247 { \ 248 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 249 }; \ 250 \ 251 template <class T, class U, class B = operators_detail::empty_base<T> > \ 252 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 253 { \ 254 friend T operator OP( const U& lhs, const T& rhs ) \ 255 { return T( lhs ) OP##= rhs; } \ 256 }; \ 257 \ 258 template <class T, class B = operators_detail::empty_base<T> > \ 259 struct NAME##1 : B \ 260 { \ 261 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 262 }; 263 264 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 265 266 BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) 267 BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) 268 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) 269 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) 270 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) 271 BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) 272 BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) 273 BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) 274 275 #undef BOOST_BINARY_OPERATOR_COMMUTATIVE 276 #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE 277 #undef BOOST_OPERATOR2_LEFT 278 279 // incrementable and decrementable contributed by Jeremy Siek 280 281 template <class T, class B = operators_detail::empty_base<T> > 282 struct incrementable : B 283 { operator ++(T & x,int)284 friend T operator++(T& x, int) 285 { 286 incrementable_type nrv(x); 287 ++x; 288 return nrv; 289 } 290 private: // The use of this typedef works around a Borland bug 291 typedef T incrementable_type; 292 }; 293 294 template <class T, class B = operators_detail::empty_base<T> > 295 struct decrementable : B 296 { operator --(T & x,int)297 friend T operator--(T& x, int) 298 { 299 decrementable_type nrv(x); 300 --x; 301 return nrv; 302 } 303 private: // The use of this typedef works around a Borland bug 304 typedef T decrementable_type; 305 }; 306 307 // Iterator operator classes (contributed by Jeremy Siek) ------------------// 308 309 template <class T, class P, class B = operators_detail::empty_base<T> > 310 struct dereferenceable : B 311 { operator ->boost::operators_impl::dereferenceable312 P operator->() const 313 { 314 return ::boost::addressof(*static_cast<const T&>(*this)); 315 } 316 }; 317 318 template <class T, class I, class R, class B = operators_detail::empty_base<T> > 319 struct indexable : B 320 { operator []boost::operators_impl::indexable321 R operator[](I n) const 322 { 323 return *(static_cast<const T&>(*this) + n); 324 } 325 }; 326 327 // More operator classes (contributed by Daryle Walker) --------------------// 328 // (NRVO-friendly implementation contributed by Daniel Frey) ---------------// 329 330 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 331 332 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 333 template <class T, class U, class B = operators_detail::empty_base<T> > \ 334 struct NAME##2 : B \ 335 { \ 336 friend T operator OP( const T& lhs, const U& rhs ) \ 337 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 338 }; \ 339 \ 340 template <class T, class B = operators_detail::empty_base<T> > \ 341 struct NAME##1 : B \ 342 { \ 343 friend T operator OP( const T& lhs, const T& rhs ) \ 344 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 345 }; 346 347 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 348 349 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 350 template <class T, class U, class B = operators_detail::empty_base<T> > \ 351 struct NAME##2 : B \ 352 { \ 353 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 354 }; \ 355 \ 356 template <class T, class B = operators_detail::empty_base<T> > \ 357 struct NAME##1 : B \ 358 { \ 359 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 360 }; 361 362 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 363 364 BOOST_BINARY_OPERATOR( left_shiftable, << ) 365 BOOST_BINARY_OPERATOR( right_shiftable, >> ) 366 367 #undef BOOST_BINARY_OPERATOR 368 369 template <class T, class U, class B = operators_detail::empty_base<T> > 370 struct equivalent2 : B 371 { operator ==(const T & x,const U & y)372 friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) 373 { 374 return !static_cast<bool>(x < y) && !static_cast<bool>(x > y); 375 } 376 }; 377 378 template <class T, class B = operators_detail::empty_base<T> > 379 struct equivalent1 : B 380 { operator ==(const T & x,const T & y)381 friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) 382 { 383 return !static_cast<bool>(x < y) && !static_cast<bool>(y < x); 384 } 385 }; 386 387 template <class T, class U, class B = operators_detail::empty_base<T> > 388 struct partially_ordered2 : B 389 { operator <=(const T & x,const U & y)390 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) 391 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } operator >=(const T & x,const U & y)392 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) 393 { return static_cast<bool>(x > y) || static_cast<bool>(x == y); } operator >(const U & x,const T & y)394 friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) 395 { return y < x; } operator <(const U & x,const T & y)396 friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) 397 { return y > x; } operator <=(const U & x,const T & y)398 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) 399 { return static_cast<bool>(y > x) || static_cast<bool>(y == x); } operator >=(const U & x,const T & y)400 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) 401 { return static_cast<bool>(y < x) || static_cast<bool>(y == x); } 402 }; 403 404 template <class T, class B = operators_detail::empty_base<T> > 405 struct partially_ordered1 : B 406 { operator >(const T & x,const T & y)407 friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) 408 { return y < x; } operator <=(const T & x,const T & y)409 friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) 410 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } operator >=(const T & x,const T & y)411 friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) 412 { return static_cast<bool>(y < x) || static_cast<bool>(x == y); } 413 }; 414 415 // Combined operator classes (contributed by Daryle Walker) ----------------// 416 417 template <class T, class U, class B = operators_detail::empty_base<T> > 418 struct totally_ordered2 419 : less_than_comparable2<T, U 420 , equality_comparable2<T, U, B 421 > > {}; 422 423 template <class T, class B = operators_detail::empty_base<T> > 424 struct totally_ordered1 425 : less_than_comparable1<T 426 , equality_comparable1<T, B 427 > > {}; 428 429 template <class T, class U, class B = operators_detail::empty_base<T> > 430 struct additive2 431 : addable2<T, U 432 , subtractable2<T, U, B 433 > > {}; 434 435 template <class T, class B = operators_detail::empty_base<T> > 436 struct additive1 437 : addable1<T 438 , subtractable1<T, B 439 > > {}; 440 441 template <class T, class U, class B = operators_detail::empty_base<T> > 442 struct multiplicative2 443 : multipliable2<T, U 444 , dividable2<T, U, B 445 > > {}; 446 447 template <class T, class B = operators_detail::empty_base<T> > 448 struct multiplicative1 449 : multipliable1<T 450 , dividable1<T, B 451 > > {}; 452 453 template <class T, class U, class B = operators_detail::empty_base<T> > 454 struct integer_multiplicative2 455 : multiplicative2<T, U 456 , modable2<T, U, B 457 > > {}; 458 459 template <class T, class B = operators_detail::empty_base<T> > 460 struct integer_multiplicative1 461 : multiplicative1<T 462 , modable1<T, B 463 > > {}; 464 465 template <class T, class U, class B = operators_detail::empty_base<T> > 466 struct arithmetic2 467 : additive2<T, U 468 , multiplicative2<T, U, B 469 > > {}; 470 471 template <class T, class B = operators_detail::empty_base<T> > 472 struct arithmetic1 473 : additive1<T 474 , multiplicative1<T, B 475 > > {}; 476 477 template <class T, class U, class B = operators_detail::empty_base<T> > 478 struct integer_arithmetic2 479 : additive2<T, U 480 , integer_multiplicative2<T, U, B 481 > > {}; 482 483 template <class T, class B = operators_detail::empty_base<T> > 484 struct integer_arithmetic1 485 : additive1<T 486 , integer_multiplicative1<T, B 487 > > {}; 488 489 template <class T, class U, class B = operators_detail::empty_base<T> > 490 struct bitwise2 491 : xorable2<T, U 492 , andable2<T, U 493 , orable2<T, U, B 494 > > > {}; 495 496 template <class T, class B = operators_detail::empty_base<T> > 497 struct bitwise1 498 : xorable1<T 499 , andable1<T 500 , orable1<T, B 501 > > > {}; 502 503 template <class T, class B = operators_detail::empty_base<T> > 504 struct unit_steppable 505 : incrementable<T 506 , decrementable<T, B 507 > > {}; 508 509 template <class T, class U, class B = operators_detail::empty_base<T> > 510 struct shiftable2 511 : left_shiftable2<T, U 512 , right_shiftable2<T, U, B 513 > > {}; 514 515 template <class T, class B = operators_detail::empty_base<T> > 516 struct shiftable1 517 : left_shiftable1<T 518 , right_shiftable1<T, B 519 > > {}; 520 521 template <class T, class U, class B = operators_detail::empty_base<T> > 522 struct ring_operators2 523 : additive2<T, U 524 , subtractable2_left<T, U 525 , multipliable2<T, U, B 526 > > > {}; 527 528 template <class T, class B = operators_detail::empty_base<T> > 529 struct ring_operators1 530 : additive1<T 531 , multipliable1<T, B 532 > > {}; 533 534 template <class T, class U, class B = operators_detail::empty_base<T> > 535 struct ordered_ring_operators2 536 : ring_operators2<T, U 537 , totally_ordered2<T, U, B 538 > > {}; 539 540 template <class T, class B = operators_detail::empty_base<T> > 541 struct ordered_ring_operators1 542 : ring_operators1<T 543 , totally_ordered1<T, B 544 > > {}; 545 546 template <class T, class U, class B = operators_detail::empty_base<T> > 547 struct field_operators2 548 : ring_operators2<T, U 549 , dividable2<T, U 550 , dividable2_left<T, U, B 551 > > > {}; 552 553 template <class T, class B = operators_detail::empty_base<T> > 554 struct field_operators1 555 : ring_operators1<T 556 , dividable1<T, B 557 > > {}; 558 559 template <class T, class U, class B = operators_detail::empty_base<T> > 560 struct ordered_field_operators2 561 : field_operators2<T, U 562 , totally_ordered2<T, U, B 563 > > {}; 564 565 template <class T, class B = operators_detail::empty_base<T> > 566 struct ordered_field_operators1 567 : field_operators1<T 568 , totally_ordered1<T, B 569 > > {}; 570 571 template <class T, class U, class B = operators_detail::empty_base<T> > 572 struct euclidian_ring_operators2 573 : ring_operators2<T, U 574 , dividable2<T, U 575 , dividable2_left<T, U 576 , modable2<T, U 577 , modable2_left<T, U, B 578 > > > > > {}; 579 580 template <class T, class B = operators_detail::empty_base<T> > 581 struct euclidian_ring_operators1 582 : ring_operators1<T 583 , dividable1<T 584 , modable1<T, B 585 > > > {}; 586 587 template <class T, class U, class B = operators_detail::empty_base<T> > 588 struct ordered_euclidian_ring_operators2 589 : totally_ordered2<T, U 590 , euclidian_ring_operators2<T, U, B 591 > > {}; 592 593 template <class T, class B = operators_detail::empty_base<T> > 594 struct ordered_euclidian_ring_operators1 595 : totally_ordered1<T 596 , euclidian_ring_operators1<T, B 597 > > {}; 598 599 template <class T, class U, class B = operators_detail::empty_base<T> > 600 struct euclidean_ring_operators2 601 : ring_operators2<T, U 602 , dividable2<T, U 603 , dividable2_left<T, U 604 , modable2<T, U 605 , modable2_left<T, U, B 606 > > > > > {}; 607 608 template <class T, class B = operators_detail::empty_base<T> > 609 struct euclidean_ring_operators1 610 : ring_operators1<T 611 , dividable1<T 612 , modable1<T, B 613 > > > {}; 614 615 template <class T, class U, class B = operators_detail::empty_base<T> > 616 struct ordered_euclidean_ring_operators2 617 : totally_ordered2<T, U 618 , euclidean_ring_operators2<T, U, B 619 > > {}; 620 621 template <class T, class B = operators_detail::empty_base<T> > 622 struct ordered_euclidean_ring_operators1 623 : totally_ordered1<T 624 , euclidean_ring_operators1<T, B 625 > > {}; 626 627 template <class T, class P, class B = operators_detail::empty_base<T> > 628 struct input_iteratable 629 : equality_comparable1<T 630 , incrementable<T 631 , dereferenceable<T, P, B 632 > > > {}; 633 634 template <class T, class B = operators_detail::empty_base<T> > 635 struct output_iteratable 636 : incrementable<T, B 637 > {}; 638 639 template <class T, class P, class B = operators_detail::empty_base<T> > 640 struct forward_iteratable 641 : input_iteratable<T, P, B 642 > {}; 643 644 template <class T, class P, class B = operators_detail::empty_base<T> > 645 struct bidirectional_iteratable 646 : forward_iteratable<T, P 647 , decrementable<T, B 648 > > {}; 649 650 // To avoid repeated derivation from equality_comparable, 651 // which is an indirect base class of bidirectional_iterable, 652 // random_access_iteratable must not be derived from totally_ordered1 653 // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) 654 template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> > 655 struct random_access_iteratable 656 : bidirectional_iteratable<T, P 657 , less_than_comparable1<T 658 , additive2<T, D 659 , indexable<T, D, R, B 660 > > > > {}; 661 662 663 // 664 // Here's where we put it all together, defining the xxxx forms of the templates. 665 // We also define specializations of is_chained_base<> for 666 // the xxxx, xxxx1, and xxxx2 templates. 667 // 668 669 namespace operators_detail 670 { 671 672 // A type parameter is used instead of a plain bool because Borland's compiler 673 // didn't cope well with the more obvious non-type template parameter. 674 struct true_t {}; 675 struct false_t {}; 676 677 } // namespace operators_detail 678 679 // is_chained_base<> - a traits class used to distinguish whether an operator 680 // template argument is being used for base class chaining, or is specifying a 681 // 2nd argument type. 682 683 // Unspecialized version assumes that most types are not being used for base 684 // class chaining. We specialize for the operator templates defined in this 685 // library. 686 template<class T> struct is_chained_base { 687 typedef operators_detail::false_t value; 688 }; 689 690 // Provide a specialization of 'is_chained_base<>' 691 // for a 4-type-argument operator template. 692 # define BOOST_OPERATOR_TEMPLATE4(template_name4) \ 693 template<class T, class U, class V, class W, class B> \ 694 struct is_chained_base< template_name4<T, U, V, W, B> > { \ 695 typedef operators_detail::true_t value; \ 696 }; 697 698 // Provide a specialization of 'is_chained_base<>' 699 // for a 3-type-argument operator template. 700 # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ 701 template<class T, class U, class V, class B> \ 702 struct is_chained_base< template_name3<T, U, V, B> > { \ 703 typedef operators_detail::true_t value; \ 704 }; 705 706 // Provide a specialization of 'is_chained_base<>' 707 // for a 2-type-argument operator template. 708 # define BOOST_OPERATOR_TEMPLATE2(template_name2) \ 709 template<class T, class U, class B> \ 710 struct is_chained_base< template_name2<T, U, B> > { \ 711 typedef operators_detail::true_t value; \ 712 }; 713 714 // Provide a specialization of 'is_chained_base<>' 715 // for a 1-type-argument operator template. 716 # define BOOST_OPERATOR_TEMPLATE1(template_name1) \ 717 template<class T, class B> \ 718 struct is_chained_base< template_name1<T, B> > { \ 719 typedef operators_detail::true_t value; \ 720 }; 721 722 // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it 723 // can be used for specifying both 1-argument and 2-argument forms. Requires the 724 // existence of two previously defined class templates named '<template_name>1' 725 // and '<template_name>2' which must implement the corresponding 1- and 2- 726 // argument forms. 727 // 728 // The template type parameter O == is_chained_base<U>::value is used to 729 // distinguish whether the 2nd argument to <template_name> is being used for 730 // base class chaining from another boost operator template or is describing a 731 // 2nd operand type. O == true_t only when U is actually an another operator 732 // template from the library. Partial specialization is used to select an 733 // implementation in terms of either '<template_name>1' or '<template_name>2'. 734 // 735 736 # define BOOST_OPERATOR_TEMPLATE(template_name) \ 737 template <class T \ 738 ,class U = T \ 739 ,class B = operators_detail::empty_base<T> \ 740 ,class O = typename is_chained_base<U>::value \ 741 > \ 742 struct template_name; \ 743 \ 744 template<class T, class U, class B> \ 745 struct template_name<T, U, B, operators_detail::false_t> \ 746 : template_name##2<T, U, B> {}; \ 747 \ 748 template<class T, class U> \ 749 struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \ 750 : template_name##1<T, U> {}; \ 751 \ 752 template <class T, class B> \ 753 struct template_name<T, T, B, operators_detail::false_t> \ 754 : template_name##1<T, B> {}; \ 755 \ 756 template<class T, class U, class B, class O> \ 757 struct is_chained_base< template_name<T, U, B, O> > { \ 758 typedef operators_detail::true_t value; \ 759 }; \ 760 \ 761 BOOST_OPERATOR_TEMPLATE2(template_name##2) \ 762 BOOST_OPERATOR_TEMPLATE1(template_name##1) 763 764 BOOST_OPERATOR_TEMPLATE(less_than_comparable) 765 BOOST_OPERATOR_TEMPLATE(equality_comparable) 766 BOOST_OPERATOR_TEMPLATE(multipliable) 767 BOOST_OPERATOR_TEMPLATE(addable) 768 BOOST_OPERATOR_TEMPLATE(subtractable) 769 BOOST_OPERATOR_TEMPLATE2(subtractable2_left) 770 BOOST_OPERATOR_TEMPLATE(dividable) 771 BOOST_OPERATOR_TEMPLATE2(dividable2_left) 772 BOOST_OPERATOR_TEMPLATE(modable) 773 BOOST_OPERATOR_TEMPLATE2(modable2_left) 774 BOOST_OPERATOR_TEMPLATE(xorable) 775 BOOST_OPERATOR_TEMPLATE(andable) 776 BOOST_OPERATOR_TEMPLATE(orable) 777 778 BOOST_OPERATOR_TEMPLATE1(incrementable) 779 BOOST_OPERATOR_TEMPLATE1(decrementable) 780 781 BOOST_OPERATOR_TEMPLATE2(dereferenceable) 782 BOOST_OPERATOR_TEMPLATE3(indexable) 783 784 BOOST_OPERATOR_TEMPLATE(left_shiftable) 785 BOOST_OPERATOR_TEMPLATE(right_shiftable) 786 BOOST_OPERATOR_TEMPLATE(equivalent) 787 BOOST_OPERATOR_TEMPLATE(partially_ordered) 788 789 BOOST_OPERATOR_TEMPLATE(totally_ordered) 790 BOOST_OPERATOR_TEMPLATE(additive) 791 BOOST_OPERATOR_TEMPLATE(multiplicative) 792 BOOST_OPERATOR_TEMPLATE(integer_multiplicative) 793 BOOST_OPERATOR_TEMPLATE(arithmetic) 794 BOOST_OPERATOR_TEMPLATE(integer_arithmetic) 795 BOOST_OPERATOR_TEMPLATE(bitwise) 796 BOOST_OPERATOR_TEMPLATE1(unit_steppable) 797 BOOST_OPERATOR_TEMPLATE(shiftable) 798 BOOST_OPERATOR_TEMPLATE(ring_operators) 799 BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) 800 BOOST_OPERATOR_TEMPLATE(field_operators) 801 BOOST_OPERATOR_TEMPLATE(ordered_field_operators) 802 BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) 803 BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) 804 BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) 805 BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) 806 BOOST_OPERATOR_TEMPLATE2(input_iteratable) 807 BOOST_OPERATOR_TEMPLATE1(output_iteratable) 808 BOOST_OPERATOR_TEMPLATE2(forward_iteratable) 809 BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) 810 BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) 811 812 #undef BOOST_OPERATOR_TEMPLATE 813 #undef BOOST_OPERATOR_TEMPLATE4 814 #undef BOOST_OPERATOR_TEMPLATE3 815 #undef BOOST_OPERATOR_TEMPLATE2 816 #undef BOOST_OPERATOR_TEMPLATE1 817 818 template <class T, class U> 819 struct operators2 820 : totally_ordered2<T,U 821 , integer_arithmetic2<T,U 822 , bitwise2<T,U 823 > > > {}; 824 825 template <class T, class U = T> 826 struct operators : operators2<T, U> {}; 827 828 template <class T> struct operators<T, T> 829 : totally_ordered<T 830 , integer_arithmetic<T 831 , bitwise<T 832 , unit_steppable<T 833 > > > > {}; 834 835 // Iterator helper classes (contributed by Jeremy Siek) -------------------// 836 // (Input and output iterator helpers contributed by Daryle Walker) -------// 837 // (Changed to use combined operator classes by Daryle Walker) ------------// 838 // (Adapted to C++17 by Daniel Frey) --------------------------------------// 839 template <class Category, 840 class T, 841 class Distance = std::ptrdiff_t, 842 class Pointer = T*, 843 class Reference = T&> 844 struct iterator_helper 845 { 846 typedef Category iterator_category; 847 typedef T value_type; 848 typedef Distance difference_type; 849 typedef Pointer pointer; 850 typedef Reference reference; 851 }; 852 853 template <class T, 854 class V, 855 class D = std::ptrdiff_t, 856 class P = V const *, 857 class R = V const &> 858 struct input_iterator_helper 859 : input_iteratable<T, P 860 , iterator_helper<std::input_iterator_tag, V, D, P, R 861 > > {}; 862 863 template<class T> 864 struct output_iterator_helper 865 : output_iteratable<T 866 , iterator_helper<std::output_iterator_tag, void, void, void, void 867 > > 868 { operator *boost::operators_impl::output_iterator_helper869 T& operator*() { return static_cast<T&>(*this); } operator ++boost::operators_impl::output_iterator_helper870 T& operator++() { return static_cast<T&>(*this); } 871 }; 872 873 template <class T, 874 class V, 875 class D = std::ptrdiff_t, 876 class P = V*, 877 class R = V&> 878 struct forward_iterator_helper 879 : forward_iteratable<T, P 880 , iterator_helper<std::forward_iterator_tag, V, D, P, R 881 > > {}; 882 883 template <class T, 884 class V, 885 class D = std::ptrdiff_t, 886 class P = V*, 887 class R = V&> 888 struct bidirectional_iterator_helper 889 : bidirectional_iteratable<T, P 890 , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R 891 > > {}; 892 893 template <class T, 894 class V, 895 class D = std::ptrdiff_t, 896 class P = V*, 897 class R = V&> 898 struct random_access_iterator_helper 899 : random_access_iteratable<T, P, D, R 900 , iterator_helper<std::random_access_iterator_tag, V, D, P, R 901 > > 902 { requires_difference_operator(const T & x,const T & y)903 friend D requires_difference_operator(const T& x, const T& y) { 904 return x - y; 905 } 906 }; // random_access_iterator_helper 907 908 } // namespace operators_impl 909 using namespace operators_impl; 910 911 } // namespace boost 912 913 #if defined(__sgi) && !defined(__GNUC__) 914 #pragma reset woff 1234 915 #endif 916 917 #endif // BOOST_NO_OPERATORS_IN_NAMESPACE 918 #endif // BOOST_OPERATORS_HPP 919