1 // 2 // (C) Copyright Jeremy Siek 2000. 3 // Copyright 2002 The Trustees of Indiana University. 4 // 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 // Revision History: 10 // 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) 11 // 02 April 2001: Removed limits header altogether. (Jeremy Siek) 12 // 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock) 13 // 14 15 // See http://www.boost.org/libs/concept_check for documentation. 16 17 #ifndef BOOST_CONCEPT_CHECKS_HPP 18 # define BOOST_CONCEPT_CHECKS_HPP 19 20 # include <boost/concept/assert.hpp> 21 22 # include <boost/iterator.hpp> 23 # include <boost/type_traits/conversion_traits.hpp> 24 # include <utility> 25 # include <boost/type_traits/is_same.hpp> 26 # include <boost/type_traits/is_void.hpp> 27 # include <boost/mpl/assert.hpp> 28 # include <boost/mpl/bool.hpp> 29 # include <boost/detail/workaround.hpp> 30 # include <boost/detail/iterator.hpp> 31 32 # include <boost/concept/usage.hpp> 33 # include <boost/concept/detail/concept_def.hpp> 34 35 namespace boost 36 { 37 38 // 39 // Backward compatibility 40 // 41 42 template <class Model> function_requires(Model * =0)43 inline void function_requires(Model* = 0) 44 { 45 BOOST_CONCEPT_ASSERT((Model)); 46 } ignore_unused_variable_warning(T const &)47 template <class T> inline void ignore_unused_variable_warning(T const&) {} 48 49 # define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ 50 BOOST_CONCEPT_ASSERT((ns::concept<type_var>)) 51 52 # define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ 53 BOOST_CONCEPT_ASSERT((ns::concept<type_var1,type_var2>)) 54 55 # define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ 56 BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3>)) 57 58 # define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ 59 BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3,tv4>)) 60 61 62 // 63 // Begin concept definitions 64 // 65 BOOST_concept(Integer, (T)) 66 { BOOST_CONCEPT_USAGE(Integer)67 BOOST_CONCEPT_USAGE(Integer) 68 { 69 x.error_type_must_be_an_integer_type(); 70 } 71 private: 72 T x; 73 }; 74 75 template <> struct Integer<char> {}; 76 template <> struct Integer<signed char> {}; 77 template <> struct Integer<unsigned char> {}; 78 template <> struct Integer<short> {}; 79 template <> struct Integer<unsigned short> {}; 80 template <> struct Integer<int> {}; 81 template <> struct Integer<unsigned int> {}; 82 template <> struct Integer<long> {}; 83 template <> struct Integer<unsigned long> {}; 84 # if defined(BOOST_HAS_LONG_LONG) 85 template <> struct Integer< ::boost::long_long_type> {}; 86 template <> struct Integer< ::boost::ulong_long_type> {}; 87 # elif defined(BOOST_HAS_MS_INT64) 88 template <> struct Integer<__int64> {}; 89 template <> struct Integer<unsigned __int64> {}; 90 # endif 91 92 BOOST_concept(SignedInteger,(T)) { BOOST_CONCEPT_USAGE(SignedInteger)93 BOOST_CONCEPT_USAGE(SignedInteger) { 94 x.error_type_must_be_a_signed_integer_type(); 95 } 96 private: 97 T x; 98 }; 99 template <> struct SignedInteger<signed char> { }; 100 template <> struct SignedInteger<short> {}; 101 template <> struct SignedInteger<int> {}; 102 template <> struct SignedInteger<long> {}; 103 # if defined(BOOST_HAS_LONG_LONG) 104 template <> struct SignedInteger< ::boost::long_long_type> {}; 105 # elif defined(BOOST_HAS_MS_INT64) 106 template <> struct SignedInteger<__int64> {}; 107 # endif 108 109 BOOST_concept(UnsignedInteger,(T)) { 110 BOOST_CONCEPT_USAGE(UnsignedInteger) { 111 x.error_type_must_be_an_unsigned_integer_type(); 112 } 113 private: 114 T x; 115 }; 116 117 template <> struct UnsignedInteger<unsigned char> {}; 118 template <> struct UnsignedInteger<unsigned short> {}; 119 template <> struct UnsignedInteger<unsigned int> {}; 120 template <> struct UnsignedInteger<unsigned long> {}; 121 # if defined(BOOST_HAS_LONG_LONG) 122 template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; 123 # elif defined(BOOST_HAS_MS_INT64) 124 template <> struct UnsignedInteger<unsigned __int64> {}; 125 # endif 126 127 //=========================================================================== 128 // Basic Concepts 129 130 BOOST_concept(DefaultConstructible,(TT)) 131 { 132 BOOST_CONCEPT_USAGE(DefaultConstructible) { 133 TT a; // require default constructor 134 ignore_unused_variable_warning(a); 135 } 136 }; 137 138 BOOST_concept(Assignable,(TT)) 139 { 140 BOOST_CONCEPT_USAGE(Assignable) { 141 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL 142 a = b; // require assignment operator 143 #endif 144 const_constraints(b); 145 } 146 private: 147 void const_constraints(const TT& x) { 148 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL 149 a = x; // const required for argument to assignment 150 #else 151 ignore_unused_variable_warning(x); 152 #endif 153 } 154 private: 155 TT a; 156 TT b; 157 }; 158 159 160 BOOST_concept(CopyConstructible,(TT)) 161 { 162 BOOST_CONCEPT_USAGE(CopyConstructible) { 163 TT a(b); // require copy constructor 164 TT* ptr = &a; // require address of operator 165 const_constraints(a); 166 ignore_unused_variable_warning(ptr); 167 } 168 private: 169 void const_constraints(const TT& a) { 170 TT c(a); // require const copy constructor 171 const TT* ptr = &a; // require const address of operator 172 ignore_unused_variable_warning(c); 173 ignore_unused_variable_warning(ptr); 174 } 175 TT b; 176 }; 177 178 #if (defined _MSC_VER) 179 # pragma warning( push ) 180 # pragma warning( disable : 4510 ) // default constructor could not be generated 181 # pragma warning( disable : 4610 ) // object 'class' can never be instantiated - user-defined constructor required 182 #endif 183 // The SGI STL version of Assignable requires copy constructor and operator= 184 BOOST_concept(SGIAssignable,(TT)) 185 { 186 BOOST_CONCEPT_USAGE(SGIAssignable) { 187 TT c(a); 188 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL 189 a = b; // require assignment operator 190 #endif 191 const_constraints(b); 192 ignore_unused_variable_warning(c); 193 } 194 private: 195 void const_constraints(const TT& x) { 196 TT c(x); 197 #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL 198 a = x; // const required for argument to assignment 199 #endif 200 ignore_unused_variable_warning(c); 201 } 202 TT a; 203 TT b; 204 }; 205 #if (defined _MSC_VER) 206 # pragma warning( pop ) 207 #endif 208 209 BOOST_concept(Convertible,(X)(Y)) 210 { 211 BOOST_CONCEPT_USAGE(Convertible) { 212 Y y = x; 213 ignore_unused_variable_warning(y); 214 } 215 private: 216 X x; 217 }; 218 219 // The C++ standard requirements for many concepts talk about return 220 // types that must be "convertible to bool". The problem with this 221 // requirement is that it leaves the door open for evil proxies that 222 // define things like operator|| with strange return types. Two 223 // possible solutions are: 224 // 1) require the return type to be exactly bool 225 // 2) stay with convertible to bool, and also 226 // specify stuff about all the logical operators. 227 // For now we just test for convertible to bool. 228 template <class TT> 229 void require_boolean_expr(const TT& t) { 230 bool x = t; 231 ignore_unused_variable_warning(x); 232 } 233 234 BOOST_concept(EqualityComparable,(TT)) 235 { 236 BOOST_CONCEPT_USAGE(EqualityComparable) { 237 require_boolean_expr(a == b); 238 require_boolean_expr(a != b); 239 } 240 private: 241 TT a, b; 242 }; 243 244 BOOST_concept(LessThanComparable,(TT)) 245 { 246 BOOST_CONCEPT_USAGE(LessThanComparable) { 247 require_boolean_expr(a < b); 248 } 249 private: 250 TT a, b; 251 }; 252 253 // This is equivalent to SGI STL's LessThanComparable. 254 BOOST_concept(Comparable,(TT)) 255 { 256 BOOST_CONCEPT_USAGE(Comparable) { 257 require_boolean_expr(a < b); 258 require_boolean_expr(a > b); 259 require_boolean_expr(a <= b); 260 require_boolean_expr(a >= b); 261 } 262 private: 263 TT a, b; 264 }; 265 266 #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ 267 BOOST_concept(NAME, (First)(Second)) \ 268 { \ 269 BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ 270 private: \ 271 bool constraints_() { return a OP b; } \ 272 First a; \ 273 Second b; \ 274 } 275 276 #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ 277 BOOST_concept(NAME, (Ret)(First)(Second)) \ 278 { \ 279 BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ 280 private: \ 281 Ret constraints_() { return a OP b; } \ 282 First a; \ 283 Second b; \ 284 } 285 286 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); 287 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); 288 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOp); 289 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOp); 290 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOp); 291 BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOp); 292 293 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOp); 294 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOp); 295 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOp); 296 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOp); 297 BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOp); 298 299 //=========================================================================== 300 // Function Object Concepts 301 302 BOOST_concept(Generator,(Func)(Return)) 303 { 304 BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); } 305 306 private: 307 void test(boost::mpl::false_) 308 { 309 // Do we really want a reference here? 310 const Return& r = f(); 311 ignore_unused_variable_warning(r); 312 } 313 314 void test(boost::mpl::true_) 315 { 316 f(); 317 } 318 319 Func f; 320 }; 321 322 BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) 323 { 324 BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); } 325 326 private: 327 void test(boost::mpl::false_) 328 { 329 f(arg); // "priming the pump" this way keeps msvc6 happy (ICE) 330 Return r = f(arg); 331 ignore_unused_variable_warning(r); 332 } 333 334 void test(boost::mpl::true_) 335 { 336 f(arg); 337 } 338 339 #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ 340 && BOOST_WORKAROUND(__GNUC__, > 3))) 341 // Declare a dummy construktor to make gcc happy. 342 // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. 343 // (warning: non-static reference "const double& boost::UnaryFunction<YourClassHere>::arg" 344 // in class without a constructor [-Wuninitialized]) 345 UnaryFunction(); 346 #endif 347 348 Func f; 349 Arg arg; 350 }; 351 352 BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) 353 { 354 BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); } 355 private: 356 void test(boost::mpl::false_) 357 { 358 f(first,second); 359 Return r = f(first, second); // require operator() 360 (void)r; 361 } 362 363 void test(boost::mpl::true_) 364 { 365 f(first,second); 366 } 367 368 #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ 369 && BOOST_WORKAROUND(__GNUC__, > 3))) 370 // Declare a dummy constructor to make gcc happy. 371 // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. 372 // (warning: non-static reference "const double& boost::BinaryFunction<YourClassHere>::arg" 373 // in class without a constructor [-Wuninitialized]) 374 BinaryFunction(); 375 #endif 376 377 Func f; 378 First first; 379 Second second; 380 }; 381 382 BOOST_concept(UnaryPredicate,(Func)(Arg)) 383 { 384 BOOST_CONCEPT_USAGE(UnaryPredicate) { 385 require_boolean_expr(f(arg)); // require operator() returning bool 386 } 387 private: 388 #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ 389 && BOOST_WORKAROUND(__GNUC__, > 3))) 390 // Declare a dummy constructor to make gcc happy. 391 // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. 392 // (warning: non-static reference "const double& boost::UnaryPredicate<YourClassHere>::arg" 393 // in class without a constructor [-Wuninitialized]) 394 UnaryPredicate(); 395 #endif 396 397 Func f; 398 Arg arg; 399 }; 400 401 BOOST_concept(BinaryPredicate,(Func)(First)(Second)) 402 { 403 BOOST_CONCEPT_USAGE(BinaryPredicate) { 404 require_boolean_expr(f(a, b)); // require operator() returning bool 405 } 406 private: 407 #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ 408 && BOOST_WORKAROUND(__GNUC__, > 3))) 409 // Declare a dummy constructor to make gcc happy. 410 // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. 411 // (warning: non-static reference "const double& boost::BinaryPredicate<YourClassHere>::arg" 412 // in class without a constructor [-Wuninitialized]) 413 BinaryPredicate(); 414 #endif 415 Func f; 416 First a; 417 Second b; 418 }; 419 420 // use this when functor is used inside a container class like std::set 421 BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) 422 : BinaryPredicate<Func, First, Second> 423 { 424 BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { 425 const_constraints(f); 426 } 427 private: 428 void const_constraints(const Func& fun) { 429 // operator() must be a const member function 430 require_boolean_expr(fun(a, b)); 431 } 432 #if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ 433 && BOOST_WORKAROUND(__GNUC__, > 3))) 434 // Declare a dummy constructor to make gcc happy. 435 // It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. 436 // (warning: non-static reference "const double& boost::Const_BinaryPredicate<YourClassHere>::arg" 437 // in class without a constructor [-Wuninitialized]) 438 Const_BinaryPredicate(); 439 #endif 440 441 Func f; 442 First a; 443 Second b; 444 }; 445 446 BOOST_concept(AdaptableGenerator,(Func)(Return)) 447 : Generator<Func, typename Func::result_type> 448 { 449 typedef typename Func::result_type result_type; 450 451 BOOST_CONCEPT_USAGE(AdaptableGenerator) 452 { 453 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); 454 } 455 }; 456 457 BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg)) 458 : UnaryFunction<Func, typename Func::result_type, typename Func::argument_type> 459 { 460 typedef typename Func::argument_type argument_type; 461 typedef typename Func::result_type result_type; 462 463 ~AdaptableUnaryFunction() 464 { 465 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); 466 BOOST_CONCEPT_ASSERT((Convertible<Arg, argument_type>)); 467 } 468 }; 469 470 BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second)) 471 : BinaryFunction< 472 Func 473 , typename Func::result_type 474 , typename Func::first_argument_type 475 , typename Func::second_argument_type 476 > 477 { 478 typedef typename Func::first_argument_type first_argument_type; 479 typedef typename Func::second_argument_type second_argument_type; 480 typedef typename Func::result_type result_type; 481 482 ~AdaptableBinaryFunction() 483 { 484 BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); 485 BOOST_CONCEPT_ASSERT((Convertible<First, first_argument_type>)); 486 BOOST_CONCEPT_ASSERT((Convertible<Second, second_argument_type>)); 487 } 488 }; 489 490 BOOST_concept(AdaptablePredicate,(Func)(Arg)) 491 : UnaryPredicate<Func, Arg> 492 , AdaptableUnaryFunction<Func, bool, Arg> 493 { 494 }; 495 496 BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) 497 : BinaryPredicate<Func, First, Second> 498 , AdaptableBinaryFunction<Func, bool, First, Second> 499 { 500 }; 501 502 //=========================================================================== 503 // Iterator Concepts 504 505 BOOST_concept(InputIterator,(TT)) 506 : Assignable<TT> 507 , EqualityComparable<TT> 508 { 509 typedef typename boost::detail::iterator_traits<TT>::value_type value_type; 510 typedef typename boost::detail::iterator_traits<TT>::difference_type difference_type; 511 typedef typename boost::detail::iterator_traits<TT>::reference reference; 512 typedef typename boost::detail::iterator_traits<TT>::pointer pointer; 513 typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category; 514 515 BOOST_CONCEPT_USAGE(InputIterator) 516 { 517 BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>)); 518 BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>)); 519 520 TT j(i); 521 (void)*i; // require dereference operator 522 ++j; // require preincrement operator 523 i++; // require postincrement operator 524 } 525 private: 526 TT i; 527 }; 528 529 BOOST_concept(OutputIterator,(TT)(ValueT)) 530 : Assignable<TT> 531 { 532 BOOST_CONCEPT_USAGE(OutputIterator) { 533 534 ++i; // require preincrement operator 535 i++; // require postincrement operator 536 *i++ = t; // require postincrement and assignment 537 } 538 private: 539 TT i, j; 540 ValueT t; 541 }; 542 543 BOOST_concept(ForwardIterator,(TT)) 544 : InputIterator<TT> 545 { 546 BOOST_CONCEPT_USAGE(ForwardIterator) 547 { 548 BOOST_CONCEPT_ASSERT((Convertible< 549 BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category 550 , std::forward_iterator_tag 551 >)); 552 553 typename InputIterator<TT>::reference r = *i; 554 ignore_unused_variable_warning(r); 555 } 556 557 private: 558 TT i; 559 }; 560 561 BOOST_concept(Mutable_ForwardIterator,(TT)) 562 : ForwardIterator<TT> 563 { 564 BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) { 565 *i++ = *i; // require postincrement and assignment 566 } 567 private: 568 TT i; 569 }; 570 571 BOOST_concept(BidirectionalIterator,(TT)) 572 : ForwardIterator<TT> 573 { 574 BOOST_CONCEPT_USAGE(BidirectionalIterator) 575 { 576 BOOST_CONCEPT_ASSERT((Convertible< 577 BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category 578 , std::bidirectional_iterator_tag 579 >)); 580 581 --i; // require predecrement operator 582 i--; // require postdecrement operator 583 } 584 private: 585 TT i; 586 }; 587 588 BOOST_concept(Mutable_BidirectionalIterator,(TT)) 589 : BidirectionalIterator<TT> 590 , Mutable_ForwardIterator<TT> 591 { 592 BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator) 593 { 594 *i-- = *i; // require postdecrement and assignment 595 } 596 private: 597 TT i; 598 }; 599 600 BOOST_concept(RandomAccessIterator,(TT)) 601 : BidirectionalIterator<TT> 602 , Comparable<TT> 603 { 604 BOOST_CONCEPT_USAGE(RandomAccessIterator) 605 { 606 BOOST_CONCEPT_ASSERT((Convertible< 607 BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category 608 , std::random_access_iterator_tag 609 >)); 610 611 i += n; // require assignment addition operator 612 i = i + n; i = n + i; // require addition with difference type 613 i -= n; // require assignment subtraction operator 614 i = i - n; // require subtraction with difference type 615 n = i - j; // require difference operator 616 (void)i[n]; // require element access operator 617 } 618 619 private: 620 TT a, b; 621 TT i, j; 622 typename boost::detail::iterator_traits<TT>::difference_type n; 623 }; 624 625 BOOST_concept(Mutable_RandomAccessIterator,(TT)) 626 : RandomAccessIterator<TT> 627 , Mutable_BidirectionalIterator<TT> 628 { 629 BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator) 630 { 631 i[n] = *i; // require element access and assignment 632 } 633 private: 634 TT i; 635 typename boost::detail::iterator_traits<TT>::difference_type n; 636 }; 637 638 //=========================================================================== 639 // Container s 640 641 BOOST_concept(Container,(C)) 642 : Assignable<C> 643 { 644 typedef typename C::value_type value_type; 645 typedef typename C::difference_type difference_type; 646 typedef typename C::size_type size_type; 647 typedef typename C::const_reference const_reference; 648 typedef typename C::const_pointer const_pointer; 649 typedef typename C::const_iterator const_iterator; 650 651 BOOST_CONCEPT_USAGE(Container) 652 { 653 BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>)); 654 const_constraints(c); 655 } 656 657 private: 658 void const_constraints(const C& cc) { 659 i = cc.begin(); 660 i = cc.end(); 661 n = cc.size(); 662 n = cc.max_size(); 663 b = cc.empty(); 664 } 665 C c; 666 bool b; 667 const_iterator i; 668 size_type n; 669 }; 670 671 BOOST_concept(Mutable_Container,(C)) 672 : Container<C> 673 { 674 typedef typename C::reference reference; 675 typedef typename C::iterator iterator; 676 typedef typename C::pointer pointer; 677 678 BOOST_CONCEPT_USAGE(Mutable_Container) 679 { 680 BOOST_CONCEPT_ASSERT(( 681 Assignable<typename Mutable_Container::value_type>)); 682 683 BOOST_CONCEPT_ASSERT((InputIterator<iterator>)); 684 685 i = c.begin(); 686 i = c.end(); 687 c.swap(c2); 688 } 689 690 private: 691 iterator i; 692 C c, c2; 693 }; 694 695 BOOST_concept(ForwardContainer,(C)) 696 : Container<C> 697 { 698 BOOST_CONCEPT_USAGE(ForwardContainer) 699 { 700 BOOST_CONCEPT_ASSERT(( 701 ForwardIterator< 702 typename ForwardContainer::const_iterator 703 >)); 704 } 705 }; 706 707 BOOST_concept(Mutable_ForwardContainer,(C)) 708 : ForwardContainer<C> 709 , Mutable_Container<C> 710 { 711 BOOST_CONCEPT_USAGE(Mutable_ForwardContainer) 712 { 713 BOOST_CONCEPT_ASSERT(( 714 Mutable_ForwardIterator< 715 typename Mutable_ForwardContainer::iterator 716 >)); 717 } 718 }; 719 720 BOOST_concept(ReversibleContainer,(C)) 721 : ForwardContainer<C> 722 { 723 typedef typename 724 C::const_reverse_iterator 725 const_reverse_iterator; 726 727 BOOST_CONCEPT_USAGE(ReversibleContainer) 728 { 729 BOOST_CONCEPT_ASSERT(( 730 BidirectionalIterator< 731 typename ReversibleContainer::const_iterator>)); 732 733 BOOST_CONCEPT_ASSERT((BidirectionalIterator<const_reverse_iterator>)); 734 735 const_constraints(c); 736 } 737 private: 738 void const_constraints(const C& cc) 739 { 740 const_reverse_iterator i = cc.rbegin(); 741 i = cc.rend(); 742 } 743 C c; 744 }; 745 746 BOOST_concept(Mutable_ReversibleContainer,(C)) 747 : Mutable_ForwardContainer<C> 748 , ReversibleContainer<C> 749 { 750 typedef typename C::reverse_iterator reverse_iterator; 751 752 BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer) 753 { 754 typedef typename Mutable_ForwardContainer<C>::iterator iterator; 755 BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>)); 756 BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<reverse_iterator>)); 757 758 reverse_iterator i = c.rbegin(); 759 i = c.rend(); 760 } 761 private: 762 C c; 763 }; 764 765 BOOST_concept(RandomAccessContainer,(C)) 766 : ReversibleContainer<C> 767 { 768 typedef typename C::size_type size_type; 769 typedef typename C::const_reference const_reference; 770 771 BOOST_CONCEPT_USAGE(RandomAccessContainer) 772 { 773 BOOST_CONCEPT_ASSERT(( 774 RandomAccessIterator< 775 typename RandomAccessContainer::const_iterator 776 >)); 777 778 const_constraints(c); 779 } 780 private: 781 void const_constraints(const C& cc) 782 { 783 const_reference r = cc[n]; 784 ignore_unused_variable_warning(r); 785 } 786 787 C c; 788 size_type n; 789 }; 790 791 BOOST_concept(Mutable_RandomAccessContainer,(C)) 792 : Mutable_ReversibleContainer<C> 793 , RandomAccessContainer<C> 794 { 795 private: 796 typedef Mutable_RandomAccessContainer self; 797 public: 798 BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer) 799 { 800 BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>)); 801 BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>)); 802 803 typename self::reference r = c[i]; 804 ignore_unused_variable_warning(r); 805 } 806 807 private: 808 typename Mutable_ReversibleContainer<C>::size_type i; 809 C c; 810 }; 811 812 // A Sequence is inherently mutable 813 BOOST_concept(Sequence,(S)) 814 : Mutable_ForwardContainer<S> 815 // Matt Austern's book puts DefaultConstructible here, the C++ 816 // standard places it in Container --JGS 817 // ... so why aren't we following the standard? --DWA 818 , DefaultConstructible<S> 819 { 820 BOOST_CONCEPT_USAGE(Sequence) 821 { 822 S 823 c(n), 824 c2(n, t), 825 c3(first, last); 826 827 c.insert(p, t); 828 c.insert(p, n, t); 829 c.insert(p, first, last); 830 831 c.erase(p); 832 c.erase(p, q); 833 834 typename Sequence::reference r = c.front(); 835 836 ignore_unused_variable_warning(c); 837 ignore_unused_variable_warning(c2); 838 ignore_unused_variable_warning(c3); 839 ignore_unused_variable_warning(r); 840 const_constraints(c); 841 } 842 private: 843 void const_constraints(const S& c) { 844 typename Sequence::const_reference r = c.front(); 845 ignore_unused_variable_warning(r); 846 } 847 848 typename S::value_type t; 849 typename S::size_type n; 850 typename S::value_type* first, *last; 851 typename S::iterator p, q; 852 }; 853 854 BOOST_concept(FrontInsertionSequence,(S)) 855 : Sequence<S> 856 { 857 BOOST_CONCEPT_USAGE(FrontInsertionSequence) 858 { 859 c.push_front(t); 860 c.pop_front(); 861 } 862 private: 863 S c; 864 typename S::value_type t; 865 }; 866 867 BOOST_concept(BackInsertionSequence,(S)) 868 : Sequence<S> 869 { 870 BOOST_CONCEPT_USAGE(BackInsertionSequence) 871 { 872 c.push_back(t); 873 c.pop_back(); 874 typename BackInsertionSequence::reference r = c.back(); 875 ignore_unused_variable_warning(r); 876 const_constraints(c); 877 } 878 private: 879 void const_constraints(const S& cc) { 880 typename BackInsertionSequence::const_reference 881 r = cc.back(); 882 ignore_unused_variable_warning(r); 883 }; 884 S c; 885 typename S::value_type t; 886 }; 887 888 BOOST_concept(AssociativeContainer,(C)) 889 : ForwardContainer<C> 890 , DefaultConstructible<C> 891 { 892 typedef typename C::key_type key_type; 893 typedef typename C::key_compare key_compare; 894 typedef typename C::value_compare value_compare; 895 typedef typename C::iterator iterator; 896 897 BOOST_CONCEPT_USAGE(AssociativeContainer) 898 { 899 i = c.find(k); 900 r = c.equal_range(k); 901 c.erase(k); 902 c.erase(i); 903 c.erase(r.first, r.second); 904 const_constraints(c); 905 BOOST_CONCEPT_ASSERT((BinaryPredicate<key_compare,key_type,key_type>)); 906 907 typedef typename AssociativeContainer::value_type value_type_; 908 BOOST_CONCEPT_ASSERT((BinaryPredicate<value_compare,value_type_,value_type_>)); 909 } 910 911 // Redundant with the base concept, but it helps below. 912 typedef typename C::const_iterator const_iterator; 913 private: 914 void const_constraints(const C& cc) 915 { 916 ci = cc.find(k); 917 n = cc.count(k); 918 cr = cc.equal_range(k); 919 } 920 921 C c; 922 iterator i; 923 std::pair<iterator,iterator> r; 924 const_iterator ci; 925 std::pair<const_iterator,const_iterator> cr; 926 typename C::key_type k; 927 typename C::size_type n; 928 }; 929 930 BOOST_concept(UniqueAssociativeContainer,(C)) 931 : AssociativeContainer<C> 932 { 933 BOOST_CONCEPT_USAGE(UniqueAssociativeContainer) 934 { 935 C c(first, last); 936 937 pos_flag = c.insert(t); 938 c.insert(first, last); 939 940 ignore_unused_variable_warning(c); 941 } 942 private: 943 std::pair<typename C::iterator, bool> pos_flag; 944 typename C::value_type t; 945 typename C::value_type* first, *last; 946 }; 947 948 BOOST_concept(MultipleAssociativeContainer,(C)) 949 : AssociativeContainer<C> 950 { 951 BOOST_CONCEPT_USAGE(MultipleAssociativeContainer) 952 { 953 C c(first, last); 954 955 pos = c.insert(t); 956 c.insert(first, last); 957 958 ignore_unused_variable_warning(c); 959 ignore_unused_variable_warning(pos); 960 } 961 private: 962 typename C::iterator pos; 963 typename C::value_type t; 964 typename C::value_type* first, *last; 965 }; 966 967 BOOST_concept(SimpleAssociativeContainer,(C)) 968 : AssociativeContainer<C> 969 { 970 BOOST_CONCEPT_USAGE(SimpleAssociativeContainer) 971 { 972 typedef typename C::key_type key_type; 973 typedef typename C::value_type value_type; 974 BOOST_MPL_ASSERT((boost::is_same<key_type,value_type>)); 975 } 976 }; 977 978 BOOST_concept(PairAssociativeContainer,(C)) 979 : AssociativeContainer<C> 980 { 981 BOOST_CONCEPT_USAGE(PairAssociativeContainer) 982 { 983 typedef typename C::key_type key_type; 984 typedef typename C::value_type value_type; 985 typedef typename C::mapped_type mapped_type; 986 typedef std::pair<const key_type, mapped_type> required_value_type; 987 BOOST_MPL_ASSERT((boost::is_same<value_type,required_value_type>)); 988 } 989 }; 990 991 BOOST_concept(SortedAssociativeContainer,(C)) 992 : AssociativeContainer<C> 993 , ReversibleContainer<C> 994 { 995 BOOST_CONCEPT_USAGE(SortedAssociativeContainer) 996 { 997 C 998 c(kc), 999 c2(first, last), 1000 c3(first, last, kc); 1001 1002 p = c.upper_bound(k); 1003 p = c.lower_bound(k); 1004 r = c.equal_range(k); 1005 1006 c.insert(p, t); 1007 1008 ignore_unused_variable_warning(c); 1009 ignore_unused_variable_warning(c2); 1010 ignore_unused_variable_warning(c3); 1011 const_constraints(c); 1012 } 1013 1014 void const_constraints(const C& c) 1015 { 1016 kc = c.key_comp(); 1017 vc = c.value_comp(); 1018 1019 cp = c.upper_bound(k); 1020 cp = c.lower_bound(k); 1021 cr = c.equal_range(k); 1022 } 1023 1024 private: 1025 typename C::key_compare kc; 1026 typename C::value_compare vc; 1027 typename C::value_type t; 1028 typename C::key_type k; 1029 typedef typename C::iterator iterator; 1030 typedef typename C::const_iterator const_iterator; 1031 1032 typedef SortedAssociativeContainer self; 1033 iterator p; 1034 const_iterator cp; 1035 std::pair<typename self::iterator,typename self::iterator> r; 1036 std::pair<typename self::const_iterator,typename self::const_iterator> cr; 1037 typename C::value_type* first, *last; 1038 }; 1039 1040 // HashedAssociativeContainer 1041 1042 BOOST_concept(Collection,(C)) 1043 { 1044 BOOST_CONCEPT_USAGE(Collection) 1045 { 1046 boost::function_requires<boost::InputIteratorConcept<iterator> >(); 1047 boost::function_requires<boost::InputIteratorConcept<const_iterator> >(); 1048 boost::function_requires<boost::CopyConstructibleConcept<value_type> >(); 1049 const_constraints(c); 1050 i = c.begin(); 1051 i = c.end(); 1052 c.swap(c); 1053 } 1054 1055 void const_constraints(const C& cc) { 1056 ci = cc.begin(); 1057 ci = cc.end(); 1058 n = cc.size(); 1059 b = cc.empty(); 1060 } 1061 1062 private: 1063 typedef typename C::value_type value_type; 1064 typedef typename C::iterator iterator; 1065 typedef typename C::const_iterator const_iterator; 1066 typedef typename C::reference reference; 1067 typedef typename C::const_reference const_reference; 1068 // typedef typename C::pointer pointer; 1069 typedef typename C::difference_type difference_type; 1070 typedef typename C::size_type size_type; 1071 1072 C c; 1073 bool b; 1074 iterator i; 1075 const_iterator ci; 1076 size_type n; 1077 }; 1078 } // namespace boost 1079 1080 # include <boost/concept/detail/concept_undef.hpp> 1081 1082 #endif // BOOST_CONCEPT_CHECKS_HPP 1083 1084