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