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