Ticket #979: operators.hpp.diff
File operators.hpp.diff, 25.5 KB (added by , 15 years ago) |
---|
-
boost/operators.hpp
RCS file: /cvsroot/boost/boost/boost/operators.hpp,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24
8 8 // See http://www.boost.org/libs/utility/operators.htm for documentation. 9 9 10 10 // Revision History 11 // 24 May 07 Changed empty_base to depend on T, see 12 // http://svn.boost.org/trac/boost/ticket/979 11 13 // 21 Oct 02 Modified implementation of operators to allow compilers with a 12 14 // correct named return value optimization (NRVO) to produce optimal 13 15 // code. (Daniel Frey) … … 90 92 namespace boost { 91 93 namespace detail { 92 94 95 template <typename T> class empty_base { 96 93 97 // Helmut Zeisel, empty base class optimization bug with GCC 3.0.0 94 98 #if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0 95 class empty_base {96 99 bool dummy; 97 };98 #else99 class empty_base {};100 100 #endif 101 101 102 }; 103 102 104 } // namespace detail 103 105 } // namespace boost 104 106 … … 119 121 // Note that friend functions defined in a class are implicitly inline. 120 122 // See the C++ std, 11.4 [class.friend] paragraph 5 121 123 122 template <class T, class U, class B = ::boost::detail::empty_base >124 template <class T, class U, class B = ::boost::detail::empty_base<T> > 123 125 struct less_than_comparable2 : B 124 126 { 125 127 friend bool operator<=(const T& x, const U& y) { return !(x > y); } … … 130 132 friend bool operator>=(const U& x, const T& y) { return !(y > x); } 131 133 }; 132 134 133 template <class T, class B = ::boost::detail::empty_base >135 template <class T, class B = ::boost::detail::empty_base<T> > 134 136 struct less_than_comparable1 : B 135 137 { 136 138 friend bool operator>(const T& x, const T& y) { return y < x; } … … 138 140 friend bool operator>=(const T& x, const T& y) { return !(x < y); } 139 141 }; 140 142 141 template <class T, class U, class B = ::boost::detail::empty_base >143 template <class T, class U, class B = ::boost::detail::empty_base<T> > 142 144 struct equality_comparable2 : B 143 145 { 144 146 friend bool operator==(const U& y, const T& x) { return x == y; } … … 146 148 friend bool operator!=(const T& y, const U& x) { return !(y == x); } 147 149 }; 148 150 149 template <class T, class B = ::boost::detail::empty_base >151 template <class T, class B = ::boost::detail::empty_base<T> > 150 152 struct equality_comparable1 : B 151 153 { 152 154 friend bool operator!=(const T& x, const T& y) { return !(x == y); } … … 165 167 // implementation available. 166 168 167 169 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 168 template <class T, class U, class B = ::boost::detail::empty_base >\170 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 169 171 struct NAME##2 : B \ 170 172 { \ 171 173 friend T operator OP( const T& lhs, const U& rhs ) \ … … 174 176 { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ 175 177 }; \ 176 178 \ 177 template <class T, class B = ::boost::detail::empty_base >\179 template <class T, class B = ::boost::detail::empty_base<T> > \ 178 180 struct NAME##1 : B \ 179 181 { \ 180 182 friend T operator OP( const T& lhs, const T& rhs ) \ 181 183 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 182 184 }; 183 185 184 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \185 template <class T, class U, class B = ::boost::detail::empty_base > \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 }; \191 \192 template <class T, class U, class B = ::boost::detail::empty_base > \193 struct BOOST_OPERATOR2_LEFT(NAME) : B \194 { \195 friend T operator OP( const U& lhs, const T& rhs ) \196 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \197 }; \198 \199 template <class T, class B = ::boost::detail::empty_base > \200 struct NAME##1 : B \201 { \202 friend T operator OP( const T& lhs, const T& rhs ) \203 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \186 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 187 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 188 struct NAME##2 : B \ 189 { \ 190 friend T operator OP( const T& lhs, const U& rhs ) \ 191 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 192 }; \ 193 \ 194 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 195 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 196 { \ 197 friend T operator OP( const U& lhs, const T& rhs ) \ 198 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 199 }; \ 200 \ 201 template <class T, class B = ::boost::detail::empty_base<T> > \ 202 struct NAME##1 : B \ 203 { \ 204 friend T operator OP( const T& lhs, const T& rhs ) \ 205 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 204 206 }; 205 207 206 208 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) … … 210 212 // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide 211 213 // optimization opportunities to the compiler :) 212 214 213 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) 214 template <class T, class U, class B = ::boost::detail::empty_base >\215 struct NAME##2 : B 216 { 217 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } 218 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } 219 }; 220 221 template <class T, class B = ::boost::detail::empty_base >\222 struct NAME##1 : B 223 { 224 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } 215 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ 216 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 217 struct NAME##2 : B \ 218 { \ 219 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 220 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ 221 }; \ 222 \ 223 template <class T, class B = ::boost::detail::empty_base<T> > \ 224 struct NAME##1 : B \ 225 { \ 226 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ 225 227 }; 226 228 227 229 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ 228 template <class T, class U, class B = ::boost::detail::empty_base >\230 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 229 231 struct NAME##2 : B \ 230 232 { \ 231 233 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 232 234 }; \ 233 235 \ 234 template <class T, class U, class B = ::boost::detail::empty_base >\236 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 235 237 struct BOOST_OPERATOR2_LEFT(NAME) : B \ 236 238 { \ 237 239 friend T operator OP( const U& lhs, const T& rhs ) \ 238 240 { return T( lhs ) OP##= rhs; } \ 239 241 }; \ 240 242 \ 241 template <class T, class B = ::boost::detail::empty_base >\243 template <class T, class B = ::boost::detail::empty_base<T> > \ 242 244 struct NAME##1 : B \ 243 245 { \ 244 246 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ … … 261 263 262 264 // incrementable and decrementable contributed by Jeremy Siek 263 265 264 template <class T, class B = ::boost::detail::empty_base >266 template <class T, class B = ::boost::detail::empty_base<T> > 265 267 struct incrementable : B 266 268 { 267 269 friend T operator++(T& x, int) … … 274 276 typedef T incrementable_type; 275 277 }; 276 278 277 template <class T, class B = ::boost::detail::empty_base >279 template <class T, class B = ::boost::detail::empty_base<T> > 278 280 struct decrementable : B 279 281 { 280 282 friend T operator--(T& x, int) … … 289 291 290 292 // Iterator operator classes (contributed by Jeremy Siek) ------------------// 291 293 292 template <class T, class P, class B = ::boost::detail::empty_base >294 template <class T, class P, class B = ::boost::detail::empty_base<T> > 293 295 struct dereferenceable : B 294 296 { 295 297 P operator->() const … … 298 300 } 299 301 }; 300 302 301 template <class T, class I, class R, class B = ::boost::detail::empty_base >303 template <class T, class I, class R, class B = ::boost::detail::empty_base<T> > 302 304 struct indexable : B 303 305 { 304 306 R operator[](I n) const … … 313 315 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 314 316 315 317 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 316 template <class T, class U, class B = ::boost::detail::empty_base >\318 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 317 319 struct NAME##2 : B \ 318 320 { \ 319 321 friend T operator OP( const T& lhs, const U& rhs ) \ 320 322 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ 321 323 }; \ 322 324 \ 323 template <class T, class B = ::boost::detail::empty_base >\325 template <class T, class B = ::boost::detail::empty_base<T> > \ 324 326 struct NAME##1 : B \ 325 327 { \ 326 328 friend T operator OP( const T& lhs, const T& rhs ) \ … … 330 332 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) 331 333 332 334 #define BOOST_BINARY_OPERATOR( NAME, OP ) \ 333 template <class T, class U, class B = ::boost::detail::empty_base >\335 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 334 336 struct NAME##2 : B \ 335 337 { \ 336 338 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ 337 339 }; \ 338 340 \ 339 template <class T, class B = ::boost::detail::empty_base >\341 template <class T, class B = ::boost::detail::empty_base<T> > \ 340 342 struct NAME##1 : B \ 341 343 { \ 342 344 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ … … 349 351 350 352 #undef BOOST_BINARY_OPERATOR 351 353 352 template <class T, class U, class B = ::boost::detail::empty_base >354 template <class T, class U, class B = ::boost::detail::empty_base<T> > 353 355 struct equivalent2 : B 354 356 { 355 357 friend bool operator==(const T& x, const U& y) … … 358 360 } 359 361 }; 360 362 361 template <class T, class B = ::boost::detail::empty_base >363 template <class T, class B = ::boost::detail::empty_base<T> > 362 364 struct equivalent1 : B 363 365 { 364 366 friend bool operator==(const T&x, const T&y) … … 367 369 } 368 370 }; 369 371 370 template <class T, class U, class B = ::boost::detail::empty_base >372 template <class T, class U, class B = ::boost::detail::empty_base<T> > 371 373 struct partially_ordered2 : B 372 374 { 373 375 friend bool operator<=(const T& x, const U& y) … … 384 386 { return (y < x) || (y == x); } 385 387 }; 386 388 387 template <class T, class B = ::boost::detail::empty_base >389 template <class T, class B = ::boost::detail::empty_base<T> > 388 390 struct partially_ordered1 : B 389 391 { 390 392 friend bool operator>(const T& x, const T& y) … … 397 399 398 400 // Combined operator classes (contributed by Daryle Walker) ----------------// 399 401 400 template <class T, class U, class B = ::boost::detail::empty_base >402 template <class T, class U, class B = ::boost::detail::empty_base<T> > 401 403 struct totally_ordered2 402 404 : less_than_comparable2<T, U 403 405 , equality_comparable2<T, U, B 404 406 > > {}; 405 407 406 template <class T, class B = ::boost::detail::empty_base >408 template <class T, class B = ::boost::detail::empty_base<T> > 407 409 struct totally_ordered1 408 410 : less_than_comparable1<T 409 411 , equality_comparable1<T, B 410 412 > > {}; 411 413 412 template <class T, class U, class B = ::boost::detail::empty_base >414 template <class T, class U, class B = ::boost::detail::empty_base<T> > 413 415 struct additive2 414 416 : addable2<T, U 415 417 , subtractable2<T, U, B 416 418 > > {}; 417 419 418 template <class T, class B = ::boost::detail::empty_base >420 template <class T, class B = ::boost::detail::empty_base<T> > 419 421 struct additive1 420 422 : addable1<T 421 423 , subtractable1<T, B 422 424 > > {}; 423 425 424 template <class T, class U, class B = ::boost::detail::empty_base >426 template <class T, class U, class B = ::boost::detail::empty_base<T> > 425 427 struct multiplicative2 426 428 : multipliable2<T, U 427 429 , dividable2<T, U, B 428 430 > > {}; 429 431 430 template <class T, class B = ::boost::detail::empty_base >432 template <class T, class B = ::boost::detail::empty_base<T> > 431 433 struct multiplicative1 432 434 : multipliable1<T 433 435 , dividable1<T, B 434 436 > > {}; 435 437 436 template <class T, class U, class B = ::boost::detail::empty_base >438 template <class T, class U, class B = ::boost::detail::empty_base<T> > 437 439 struct integer_multiplicative2 438 440 : multiplicative2<T, U 439 441 , modable2<T, U, B 440 442 > > {}; 441 443 442 template <class T, class B = ::boost::detail::empty_base >444 template <class T, class B = ::boost::detail::empty_base<T> > 443 445 struct integer_multiplicative1 444 446 : multiplicative1<T 445 447 , modable1<T, B 446 448 > > {}; 447 449 448 template <class T, class U, class B = ::boost::detail::empty_base >450 template <class T, class U, class B = ::boost::detail::empty_base<T> > 449 451 struct arithmetic2 450 452 : additive2<T, U 451 453 , multiplicative2<T, U, B 452 454 > > {}; 453 455 454 template <class T, class B = ::boost::detail::empty_base >456 template <class T, class B = ::boost::detail::empty_base<T> > 455 457 struct arithmetic1 456 458 : additive1<T 457 459 , multiplicative1<T, B 458 460 > > {}; 459 461 460 template <class T, class U, class B = ::boost::detail::empty_base >462 template <class T, class U, class B = ::boost::detail::empty_base<T> > 461 463 struct integer_arithmetic2 462 464 : additive2<T, U 463 465 , integer_multiplicative2<T, U, B 464 466 > > {}; 465 467 466 template <class T, class B = ::boost::detail::empty_base >468 template <class T, class B = ::boost::detail::empty_base<T> > 467 469 struct integer_arithmetic1 468 470 : additive1<T 469 471 , integer_multiplicative1<T, B 470 472 > > {}; 471 473 472 template <class T, class U, class B = ::boost::detail::empty_base >474 template <class T, class U, class B = ::boost::detail::empty_base<T> > 473 475 struct bitwise2 474 476 : xorable2<T, U 475 477 , andable2<T, U 476 478 , orable2<T, U, B 477 479 > > > {}; 478 480 479 template <class T, class B = ::boost::detail::empty_base >481 template <class T, class B = ::boost::detail::empty_base<T> > 480 482 struct bitwise1 481 483 : xorable1<T 482 484 , andable1<T 483 485 , orable1<T, B 484 486 > > > {}; 485 487 486 template <class T, class B = ::boost::detail::empty_base >488 template <class T, class B = ::boost::detail::empty_base<T> > 487 489 struct unit_steppable 488 490 : incrementable<T 489 491 , decrementable<T, B 490 492 > > {}; 491 493 492 template <class T, class U, class B = ::boost::detail::empty_base >494 template <class T, class U, class B = ::boost::detail::empty_base<T> > 493 495 struct shiftable2 494 496 : left_shiftable2<T, U 495 497 , right_shiftable2<T, U, B 496 498 > > {}; 497 499 498 template <class T, class B = ::boost::detail::empty_base >500 template <class T, class B = ::boost::detail::empty_base<T> > 499 501 struct shiftable1 500 502 : left_shiftable1<T 501 503 , right_shiftable1<T, B 502 504 > > {}; 503 505 504 template <class T, class U, class B = ::boost::detail::empty_base >506 template <class T, class U, class B = ::boost::detail::empty_base<T> > 505 507 struct ring_operators2 506 508 : additive2<T, U 507 509 , subtractable2_left<T, U 508 510 , multipliable2<T, U, B 509 511 > > > {}; 510 512 511 template <class T, class B = ::boost::detail::empty_base >513 template <class T, class B = ::boost::detail::empty_base<T> > 512 514 struct ring_operators1 513 515 : additive1<T 514 516 , multipliable1<T, B 515 517 > > {}; 516 518 517 template <class T, class U, class B = ::boost::detail::empty_base >519 template <class T, class U, class B = ::boost::detail::empty_base<T> > 518 520 struct ordered_ring_operators2 519 521 : ring_operators2<T, U 520 522 , totally_ordered2<T, U, B 521 523 > > {}; 522 524 523 template <class T, class B = ::boost::detail::empty_base >525 template <class T, class B = ::boost::detail::empty_base<T> > 524 526 struct ordered_ring_operators1 525 527 : ring_operators1<T 526 528 , totally_ordered1<T, B 527 529 > > {}; 528 530 529 template <class T, class U, class B = ::boost::detail::empty_base >531 template <class T, class U, class B = ::boost::detail::empty_base<T> > 530 532 struct field_operators2 531 533 : ring_operators2<T, U 532 534 , dividable2<T, U 533 535 , dividable2_left<T, U, B 534 536 > > > {}; 535 537 536 template <class T, class B = ::boost::detail::empty_base >538 template <class T, class B = ::boost::detail::empty_base<T> > 537 539 struct field_operators1 538 540 : ring_operators1<T 539 541 , dividable1<T, B 540 542 > > {}; 541 543 542 template <class T, class U, class B = ::boost::detail::empty_base >544 template <class T, class U, class B = ::boost::detail::empty_base<T> > 543 545 struct ordered_field_operators2 544 546 : field_operators2<T, U 545 547 , totally_ordered2<T, U, B 546 548 > > {}; 547 549 548 template <class T, class B = ::boost::detail::empty_base >550 template <class T, class B = ::boost::detail::empty_base<T> > 549 551 struct ordered_field_operators1 550 552 : field_operators1<T 551 553 , totally_ordered1<T, B 552 554 > > {}; 553 555 554 template <class T, class U, class B = ::boost::detail::empty_base >556 template <class T, class U, class B = ::boost::detail::empty_base<T> > 555 557 struct euclidian_ring_operators2 556 558 : ring_operators2<T, U 557 559 , dividable2<T, U … … 560 562 , modable2_left<T, U, B 561 563 > > > > > {}; 562 564 563 template <class T, class B = ::boost::detail::empty_base >565 template <class T, class B = ::boost::detail::empty_base<T> > 564 566 struct euclidian_ring_operators1 565 567 : ring_operators1<T 566 568 , dividable1<T 567 569 , modable1<T, B 568 570 > > > {}; 569 571 570 template <class T, class U, class B = ::boost::detail::empty_base >572 template <class T, class U, class B = ::boost::detail::empty_base<T> > 571 573 struct ordered_euclidian_ring_operators2 572 574 : totally_ordered2<T, U 573 575 , euclidian_ring_operators2<T, U, B 574 576 > > {}; 575 577 576 template <class T, class B = ::boost::detail::empty_base >578 template <class T, class B = ::boost::detail::empty_base<T> > 577 579 struct ordered_euclidian_ring_operators1 578 580 : totally_ordered1<T 579 581 , euclidian_ring_operators1<T, B 580 582 > > {}; 581 583 582 template <class T, class P, class B = ::boost::detail::empty_base >584 template <class T, class P, class B = ::boost::detail::empty_base<T> > 583 585 struct input_iteratable 584 586 : equality_comparable1<T 585 587 , incrementable<T 586 588 , dereferenceable<T, P, B 587 589 > > > {}; 588 590 589 template <class T, class B = ::boost::detail::empty_base >591 template <class T, class B = ::boost::detail::empty_base<T> > 590 592 struct output_iteratable 591 593 : incrementable<T, B 592 594 > {}; 593 595 594 template <class T, class P, class B = ::boost::detail::empty_base >596 template <class T, class P, class B = ::boost::detail::empty_base<T> > 595 597 struct forward_iteratable 596 598 : input_iteratable<T, P, B 597 599 > {}; 598 600 599 template <class T, class P, class B = ::boost::detail::empty_base >601 template <class T, class P, class B = ::boost::detail::empty_base<T> > 600 602 struct bidirectional_iteratable 601 603 : forward_iteratable<T, P 602 604 , decrementable<T, B … … 606 608 // which is an indirect base class of bidirectional_iterable, 607 609 // random_access_iteratable must not be derived from totally_ordered1 608 610 // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) 609 template <class T, class P, class D, class R, class B = ::boost::detail::empty_base >611 template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> > 610 612 struct random_access_iteratable 611 613 : bidirectional_iteratable<T, P 612 614 , less_than_comparable1<T … … 650 652 651 653 // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration 652 654 // from working, we are forced to use inheritance for that compiler. 653 # define BOOST_IMPORT_TEMPLATE4(template_name) \654 template <class T, class U, class V, class W, class B = ::boost::detail::empty_base >\655 # define BOOST_IMPORT_TEMPLATE4(template_name) \ 656 template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \ 655 657 struct template_name : ::template_name<T, U, V, W, B> {}; 656 658 657 # define BOOST_IMPORT_TEMPLATE3(template_name) \658 template <class T, class U, class V, class B = ::boost::detail::empty_base >\659 # define BOOST_IMPORT_TEMPLATE3(template_name) \ 660 template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \ 659 661 struct template_name : ::template_name<T, U, V, B> {}; 660 662 661 # define BOOST_IMPORT_TEMPLATE2(template_name) 662 template <class T, class U, class B = ::boost::detail::empty_base >\663 # define BOOST_IMPORT_TEMPLATE2(template_name) \ 664 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ 663 665 struct template_name : ::template_name<T, U, B> {}; 664 666 665 # define BOOST_IMPORT_TEMPLATE1(template_name) 666 template <class T, class B = ::boost::detail::empty_base >\667 # define BOOST_IMPORT_TEMPLATE1(template_name) \ 668 template <class T, class B = ::boost::detail::empty_base<T> > \ 667 669 struct template_name : ::template_name<T, B> {}; 668 670 669 671 # endif // BOOST_NO_USING_TEMPLATE … … 752 754 # define BOOST_OPERATOR_TEMPLATE(template_name) \ 753 755 template <class T \ 754 756 ,class U = T \ 755 ,class B = ::boost::detail::empty_base 757 ,class B = ::boost::detail::empty_base<T> \ 756 758 ,class O = typename is_chained_base<U>::value \ 757 759 > \ 758 760 struct template_name : template_name##2<T, U, B> {}; \ … … 788 790 // In this case we can only assume that template_name<> is equivalent to the 789 791 // more commonly needed template_name1<> form. 790 792 # define BOOST_OPERATOR_TEMPLATE(template_name) \ 791 template <class T, class B = ::boost::detail::empty_base >\793 template <class T, class B = ::boost::detail::empty_base<T> > \ 792 794 struct template_name : template_name##1<T, B> {}; 793 795 794 796 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION