1 // Copyright (C) 2019 T. Zachary Laine 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See 4 // accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 #ifndef BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP 7 #define BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP 8 9 #include <boost/stl_interfaces/fwd.hpp> 10 11 #include <utility> 12 #include <type_traits> 13 #if defined(__cpp_lib_three_way_comparison) 14 #include <compare> 15 #endif 16 17 18 namespace boost { namespace stl_interfaces { 19 20 /** A type for granting access to the private members of an iterator 21 derived from `iterator_interface`. */ 22 struct access 23 { 24 #ifndef BOOST_STL_INTERFACES_DOXYGEN 25 26 template<typename D> baseboost::stl_interfaces::access27 static constexpr auto base(D & d) noexcept 28 -> decltype(d.base_reference()) 29 { 30 return d.base_reference(); 31 } 32 template<typename D> baseboost::stl_interfaces::access33 static constexpr auto base(D const & d) noexcept 34 -> decltype(d.base_reference()) 35 { 36 return d.base_reference(); 37 } 38 39 #endif 40 }; 41 42 /** The return type of `operator->()` in a proxy iterator. 43 44 This template is used as the default `Pointer` template parameter in 45 the `proxy_iterator_interface` template alias. Note that the use of 46 this template implies a copy or move of the underlying object of type 47 `T`. */ 48 template<typename T> 49 struct proxy_arrow_result 50 { proxy_arrow_resultboost::stl_interfaces::proxy_arrow_result51 constexpr proxy_arrow_result(T const & value) noexcept( 52 noexcept(T(value))) : 53 value_(value) 54 {} proxy_arrow_resultboost::stl_interfaces::proxy_arrow_result55 constexpr proxy_arrow_result(T && value) noexcept( 56 noexcept(T(std::move(value)))) : 57 value_(std::move(value)) 58 {} 59 operator ->boost::stl_interfaces::proxy_arrow_result60 constexpr T const * operator->() const noexcept { return &value_; } operator ->boost::stl_interfaces::proxy_arrow_result61 constexpr T * operator->() noexcept { return &value_; } 62 63 private: 64 T value_; 65 }; 66 67 namespace detail { 68 template<typename Pointer, typename T> make_pointer(T && value,std::enable_if_t<std::is_pointer<Pointer>::value,int>=0)69 auto make_pointer( 70 T && value, 71 std::enable_if_t<std::is_pointer<Pointer>::value, int> = 0) 72 -> decltype(std::addressof(value)) 73 { 74 return std::addressof(value); 75 } 76 77 template<typename Pointer, typename T> make_pointer(T && value,std::enable_if_t<!std::is_pointer<Pointer>::value,int>=0)78 auto make_pointer( 79 T && value, 80 std::enable_if_t<!std::is_pointer<Pointer>::value, int> = 0) 81 { 82 return Pointer(std::forward<T>(value)); 83 } 84 85 template<typename IteratorConcept> 86 struct concept_category 87 { 88 using type = IteratorConcept; 89 }; 90 template<typename IteratorConcept> 91 using concept_category_t = 92 typename concept_category<IteratorConcept>::type; 93 94 template<typename Pointer, typename IteratorConcept> 95 struct pointer 96 { 97 using type = Pointer; 98 }; 99 template<typename Pointer> 100 struct pointer<Pointer, std::output_iterator_tag> 101 { 102 using type = void; 103 }; 104 template<typename Pointer, typename IteratorConcept> 105 using pointer_t = typename pointer<Pointer, IteratorConcept>::type; 106 107 template<typename T, typename U> 108 using interoperable = std::integral_constant< 109 bool, 110 (std::is_convertible<T, U>::value || 111 std::is_convertible<U, T>::value)>; 112 113 template<typename T, typename U> 114 using common_t = 115 std::conditional_t<std::is_convertible<T, U>::value, U, T>; 116 117 template<typename T> 118 using use_base = decltype(access::base(std::declval<T &>())); 119 120 template<typename... T> 121 using void_t = void; 122 123 template< 124 typename AlwaysVoid, 125 template<class...> class Template, 126 typename... Args> 127 struct detector : std::false_type 128 { 129 }; 130 131 template<template<class...> class Template, typename... Args> 132 struct detector<void_t<Template<Args...>>, Template, Args...> 133 : std::true_type 134 { 135 }; 136 137 template< 138 typename T, 139 typename U, 140 bool UseBase = detector<void, use_base, T>::value> 141 struct common_eq 142 { callboost::stl_interfaces::detail::common_eq143 static constexpr auto call(T lhs, U rhs) 144 { 145 return static_cast<common_t<T, U>>(lhs).derived() == 146 static_cast<common_t<T, U>>(rhs).derived(); 147 } 148 }; 149 template<typename T, typename U> 150 struct common_eq<T, U, true> 151 { callboost::stl_interfaces::detail::common_eq152 static constexpr auto call(T lhs, U rhs) 153 { 154 return access::base(lhs) == access::base(rhs); 155 } 156 }; 157 158 template<typename T, typename U> common_diff(T lhs,U rhs)159 constexpr auto common_diff(T lhs, U rhs) noexcept(noexcept( 160 static_cast<common_t<T, U>>(lhs) - 161 static_cast<common_t<T, U>>(rhs))) 162 -> decltype( 163 static_cast<common_t<T, U>>(lhs) - 164 static_cast<common_t<T, U>>(rhs)) 165 { 166 return static_cast<common_t<T, U>>(lhs) - 167 static_cast<common_t<T, U>>(rhs); 168 } 169 } 170 171 }} 172 173 namespace boost { namespace stl_interfaces { inline namespace v1 { 174 175 /** A CRTP template that one may derive from to make defining iterators 176 easier. 177 178 The template parameter `D` for `iterator_interface` may be an 179 incomplete type. Before any member of the resulting specialization of 180 `iterator_interface` other than special member functions is 181 referenced, `D` shall be complete, and model 182 `std::derived_from<iterator_interface<D>>`. */ 183 template< 184 typename Derived, 185 typename IteratorConcept, 186 typename ValueType, 187 typename Reference = ValueType &, 188 typename Pointer = ValueType *, 189 typename DifferenceType = std::ptrdiff_t 190 #ifndef BOOST_STL_INTERFACES_DOXYGEN 191 , 192 typename E = std::enable_if_t< 193 std::is_class<Derived>::value && 194 std::is_same<Derived, std::remove_cv_t<Derived>>::value> 195 #endif 196 > 197 struct iterator_interface; 198 199 namespace v1_dtl { 200 template<typename Iterator, typename = void> 201 struct ra_iter : std::false_type 202 { 203 }; 204 template<typename Iterator> 205 struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>> 206 : std::integral_constant< 207 bool, 208 std::is_base_of< 209 std::random_access_iterator_tag, 210 typename Iterator::iterator_concept>::value> 211 { 212 }; 213 214 template<typename Iterator, typename DifferenceType, typename = void> 215 struct plus_eq : std::false_type 216 { 217 }; 218 template<typename Iterator, typename DifferenceType> 219 struct plus_eq< 220 Iterator, 221 DifferenceType, 222 void_t<decltype( 223 std::declval<Iterator &>() += std::declval<DifferenceType>())>> 224 : std::true_type 225 { 226 }; 227 228 template< 229 typename D, 230 typename IteratorConcept, 231 typename ValueType, 232 typename Reference, 233 typename Pointer, 234 typename DifferenceType> 235 void derived_iterator(iterator_interface< 236 D, 237 IteratorConcept, 238 ValueType, 239 Reference, 240 Pointer, 241 DifferenceType> const &); 242 } 243 244 template< 245 typename Derived, 246 typename IteratorConcept, 247 typename ValueType, 248 typename Reference, 249 typename Pointer, 250 typename DifferenceType 251 #ifndef BOOST_STL_INTERFACES_DOXYGEN 252 , 253 typename E 254 #endif 255 > 256 struct iterator_interface 257 { 258 #ifndef BOOST_STL_INTERFACES_DOXYGEN 259 private: derivedboost::stl_interfaces::v1::iterator_interface260 constexpr Derived & derived() noexcept 261 { 262 return static_cast<Derived &>(*this); 263 } derivedboost::stl_interfaces::v1::iterator_interface264 constexpr Derived const & derived() const noexcept 265 { 266 return static_cast<Derived const &>(*this); 267 } 268 269 template<typename T, typename U, bool UseBase> 270 friend struct detail::common_eq; 271 #endif 272 273 public: 274 using iterator_concept = IteratorConcept; 275 using iterator_category = detail::concept_category_t<iterator_concept>; 276 using value_type = std::remove_const_t<ValueType>; 277 using reference = Reference; 278 using pointer = detail::pointer_t<Pointer, iterator_concept>; 279 using difference_type = DifferenceType; 280 281 template<typename D = Derived> operator *boost::stl_interfaces::v1::iterator_interface282 constexpr auto operator*() const 283 noexcept(noexcept(*access::base(std::declval<D const &>()))) 284 -> decltype(*access::base(std::declval<D const &>())) 285 { 286 return *access::base(derived()); 287 } 288 289 template<typename D = Derived> operator ->boost::stl_interfaces::v1::iterator_interface290 constexpr auto operator-> () const noexcept( 291 noexcept(detail::make_pointer<pointer>(*std::declval<D const &>()))) 292 -> decltype( 293 detail::make_pointer<pointer>(*std::declval<D const &>())) 294 { 295 return detail::make_pointer<pointer>(*derived()); 296 } 297 298 template<typename D = Derived> operator []boost::stl_interfaces::v1::iterator_interface299 constexpr auto operator[](difference_type i) const noexcept(noexcept( 300 D(std::declval<D const &>()), 301 std::declval<D &>() += i, 302 *std::declval<D &>())) 303 -> decltype(std::declval<D &>() += i, *std::declval<D &>()) 304 { 305 D retval = derived(); 306 retval += i; 307 return *retval; 308 } 309 310 template< 311 typename D = Derived, 312 typename Enable = 313 std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>> 314 constexpr auto operator ++boost::stl_interfaces::v1::iterator_interface315 operator++() noexcept(noexcept(++access::base(std::declval<D &>()))) 316 -> decltype(++access::base(std::declval<D &>())) 317 { 318 return ++access::base(derived()); 319 } 320 321 template<typename D = Derived> operator ++boost::stl_interfaces::v1::iterator_interface322 constexpr auto operator++() noexcept( 323 noexcept(std::declval<D &>() += difference_type(1))) 324 -> decltype( 325 std::declval<D &>() += difference_type(1), std::declval<D &>()) 326 { 327 derived() += difference_type(1); 328 return derived(); 329 } 330 template<typename D = Derived> operator ++boost::stl_interfaces::v1::iterator_interface331 constexpr auto operator++(int)noexcept( 332 noexcept(D(std::declval<D &>()), ++std::declval<D &>())) 333 -> std::remove_reference_t<decltype( 334 D(std::declval<D &>()), 335 ++std::declval<D &>(), 336 std::declval<D &>())> 337 { 338 D retval = derived(); 339 ++derived(); 340 return retval; 341 } 342 343 template<typename D = Derived> operator +=boost::stl_interfaces::v1::iterator_interface344 constexpr auto operator+=(difference_type n) noexcept( 345 noexcept(access::base(std::declval<D &>()) += n)) 346 -> decltype(access::base(std::declval<D &>()) += n) 347 { 348 return access::base(derived()) += n; 349 } 350 351 template<typename D = Derived> operator +boost::stl_interfaces::v1::iterator_interface352 constexpr auto operator+(difference_type i) const 353 noexcept(noexcept(D(std::declval<D &>()), std::declval<D &>() += i)) 354 -> std::remove_reference_t<decltype( 355 D(std::declval<D &>()), 356 std::declval<D &>() += i, 357 std::declval<D &>())> 358 { 359 D retval = derived(); 360 retval += i; 361 return retval; 362 } 363 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived operator +(difference_type i,Derived it)364 operator+(difference_type i, Derived it) noexcept 365 { 366 return it + i; 367 } 368 369 template< 370 typename D = Derived, 371 typename Enable = 372 std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>> 373 constexpr auto operator --boost::stl_interfaces::v1::iterator_interface374 operator--() noexcept(noexcept(--access::base(std::declval<D &>()))) 375 -> decltype(--access::base(std::declval<D &>())) 376 { 377 return --access::base(derived()); 378 } 379 380 template<typename D = Derived> operator --boost::stl_interfaces::v1::iterator_interface381 constexpr auto operator--() noexcept(noexcept( 382 D(std::declval<D &>()), std::declval<D &>() += -difference_type(1))) 383 -> decltype( 384 std::declval<D &>() += -difference_type(1), std::declval<D &>()) 385 { 386 derived() += -difference_type(1); 387 return derived(); 388 } 389 template<typename D = Derived> operator --boost::stl_interfaces::v1::iterator_interface390 constexpr auto operator--(int)noexcept( 391 noexcept(D(std::declval<D &>()), --std::declval<D &>())) 392 -> std::remove_reference_t<decltype( 393 D(std::declval<D &>()), 394 --std::declval<D &>(), 395 std::declval<D &>())> 396 { 397 D retval = derived(); 398 --derived(); 399 return retval; 400 } 401 402 template<typename D = Derived> operator -=boost::stl_interfaces::v1::iterator_interface403 constexpr D & operator-=(difference_type i) noexcept 404 { 405 derived() += -i; 406 return derived(); 407 } 408 409 template<typename D = Derived> operator -boost::stl_interfaces::v1::iterator_interface410 constexpr auto operator-(D other) const noexcept(noexcept( 411 access::base(std::declval<D const &>()) - access::base(other))) 412 -> decltype( 413 access::base(std::declval<D const &>()) - access::base(other)) 414 { 415 return access::base(derived()) - access::base(other); 416 } 417 418 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived operator -(Derived it,difference_type i)419 operator-(Derived it, difference_type i) noexcept 420 { 421 Derived retval = it; 422 retval += -i; 423 return retval; 424 } 425 }; 426 427 /** Implementation of `operator==()`, implemented in terms of the iterator 428 underlying IteratorInterface, for all iterators derived from 429 `iterator_interface`, except those with an iterator category derived 430 from `std::random_access_iterator_tag`. */ 431 template< 432 typename IteratorInterface1, 433 typename IteratorInterface2, 434 typename Enable = 435 std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>> 436 constexpr auto operator ==(IteratorInterface1 lhs,IteratorInterface2 rhs)437 operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept 438 -> decltype( 439 access::base(std::declval<IteratorInterface1 &>()) == 440 access::base(std::declval<IteratorInterface2 &>())) 441 { 442 return access::base(lhs) == access::base(rhs); 443 } 444 445 /** Implementation of `operator==()` for all iterators derived from 446 `iterator_interface` that have an iterator category derived from 447 `std::random_access_iterator_tag`. */ 448 template< 449 typename IteratorInterface1, 450 typename IteratorInterface2, 451 typename Enable = 452 std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>> 453 constexpr auto operator ==(IteratorInterface1 lhs,IteratorInterface2 rhs)454 operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept( 455 noexcept(detail::common_diff(lhs, rhs))) 456 -> decltype( 457 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0) 458 { 459 return detail::common_diff(lhs, rhs) == 0; 460 } 461 462 /** Implementation of `operator!=()` for all iterators derived from 463 `iterator_interface`. */ 464 template<typename IteratorInterface1, typename IteratorInterface2> operator !=(IteratorInterface1 lhs,IteratorInterface2 rhs)465 constexpr auto operator!=( 466 IteratorInterface1 lhs, 467 IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs))) 468 -> decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs)) 469 { 470 return !(lhs == rhs); 471 } 472 473 /** Implementation of `operator<()` for all iterators derived from 474 `iterator_interface` that have an iterator category derived from 475 `std::random_access_iterator_tag`. */ 476 template<typename IteratorInterface1, typename IteratorInterface2> 477 constexpr auto operator <(IteratorInterface1 lhs,IteratorInterface2 rhs)478 operator<(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept( 479 noexcept(detail::common_diff(lhs, rhs))) 480 -> decltype( 481 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0) 482 { 483 return detail::common_diff(lhs, rhs) < 0; 484 } 485 486 /** Implementation of `operator<=()` for all iterators derived from 487 `iterator_interface` that have an iterator category derived from 488 `std::random_access_iterator_tag`. */ 489 template<typename IteratorInterface1, typename IteratorInterface2> 490 constexpr auto operator <=(IteratorInterface1 lhs,IteratorInterface2 rhs)491 operator<=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept( 492 noexcept(detail::common_diff(lhs, rhs))) 493 -> decltype( 494 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0) 495 { 496 return detail::common_diff(lhs, rhs) <= 0; 497 } 498 499 /** Implementation of `operator>()` for all iterators derived from 500 `iterator_interface` that have an iterator category derived from 501 `std::random_access_iterator_tag`. */ 502 template<typename IteratorInterface1, typename IteratorInterface2> 503 constexpr auto operator >(IteratorInterface1 lhs,IteratorInterface2 rhs)504 operator>(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept( 505 noexcept(detail::common_diff(lhs, rhs))) 506 -> decltype( 507 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0) 508 { 509 return detail::common_diff(lhs, rhs) > 0; 510 } 511 512 /** Implementation of `operator>=()` for all iterators derived from 513 `iterator_interface` that have an iterator category derived from 514 `std::random_access_iterator_tag`. */ 515 template<typename IteratorInterface1, typename IteratorInterface2> 516 constexpr auto operator >=(IteratorInterface1 lhs,IteratorInterface2 rhs)517 operator>=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept( 518 noexcept(detail::common_diff(lhs, rhs))) 519 -> decltype( 520 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0) 521 { 522 return detail::common_diff(lhs, rhs) >= 0; 523 } 524 525 526 /** A template alias useful for defining proxy iterators. \see 527 `iterator_interface`. */ 528 template< 529 typename Derived, 530 typename IteratorConcept, 531 typename ValueType, 532 typename Reference = ValueType, 533 typename DifferenceType = std::ptrdiff_t> 534 using proxy_iterator_interface = iterator_interface< 535 Derived, 536 IteratorConcept, 537 ValueType, 538 Reference, 539 proxy_arrow_result<Reference>, 540 DifferenceType>; 541 542 }}} 543 544 #if 201703L < __cplusplus && defined(__cpp_lib_ranges) 545 546 namespace boost { namespace stl_interfaces { namespace v2 { namespace detail { 547 548 template<typename Iterator> 549 struct iter_concept; 550 551 template<typename Iterator> 552 requires requires 553 { 554 typename std::iterator_traits<Iterator>::iterator_concept; 555 } 556 struct iter_concept<Iterator> 557 { 558 using type = typename std::iterator_traits<Iterator>::iterator_concept; 559 }; 560 561 template<typename Iterator> 562 requires( 563 !requires { 564 typename std::iterator_traits<Iterator>::iterator_concept; 565 } && 566 requires { 567 typename std::iterator_traits<Iterator>::iterator_category; 568 }) struct iter_concept<Iterator> 569 { 570 using type = typename std::iterator_traits<Iterator>::iterator_category; 571 }; 572 573 template<typename Iterator> 574 requires( 575 !requires { 576 typename std::iterator_traits<Iterator>::iterator_concept; 577 } && 578 !requires { 579 typename std::iterator_traits<Iterator>::iterator_category; 580 }) struct iter_concept<Iterator> 581 { 582 using type = std::random_access_iterator_tag; 583 }; 584 585 template<typename Iterator> 586 struct iter_concept 587 {}; 588 589 template<typename Iterator> 590 using iter_concept_t = typename iter_concept<Iterator>::type; 591 592 }}}} 593 594 #endif 595 596 #ifdef BOOST_STL_INTERFACES_DOXYGEN 597 598 /** `static_asserts` that type `type` models concept `concept_name`. This is 599 useful for checking that an iterator, view, etc. that you write using one 600 of the *`_interface` templates models the right C++ concept. 601 602 For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter, 603 std::input_iterator)`. 604 605 \note This macro expands to nothing when `__cpp_lib_concepts` is not 606 defined. */ 607 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name) 608 609 /** `static_asserts` that the types of all typedefs in 610 `std::iterator_traits<iter>` match the remaining macro parameters. This 611 is useful for checking that an iterator you write using 612 `iterator_interface` has the correct iterator traits. 613 614 For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter, 615 std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t)`. 616 617 \note This macro ignores the `concept` parameter when `__cpp_lib_concepts` 618 is not defined. */ 619 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \ 620 iter, category, concept, value_type, reference, pointer, difference_type) 621 622 #else 623 624 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \ 625 type, concept_name) \ 626 static_assert(concept_name<type>, ""); 627 628 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name) 629 630 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ 631 iter, category, value_t, ref, ptr, diff_t) \ 632 static_assert( \ 633 std::is_same< \ 634 typename std::iterator_traits<iter>::iterator_category, \ 635 category>::value, \ 636 ""); \ 637 static_assert( \ 638 std::is_same< \ 639 typename std::iterator_traits<iter>::value_type, \ 640 value_t>::value, \ 641 ""); \ 642 static_assert( \ 643 std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \ 644 value, \ 645 ""); \ 646 static_assert( \ 647 std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \ 648 value, \ 649 ""); \ 650 static_assert( \ 651 std::is_same< \ 652 typename std::iterator_traits<iter>::difference_type, \ 653 diff_t>::value, \ 654 ""); 655 656 #if 201703L < __cplusplus && defined(__cpp_lib_ranges) 657 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \ 658 iter, category, concept, value_type, reference, pointer, difference_type) \ 659 static_assert( \ 660 std::is_same_v< \ 661 boost::stl_interfaces::v2::detail::iter_concept_t<iter>, \ 662 concept>, \ 663 ""); \ 664 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ 665 iter, category, value_type, reference, pointer, difference_type) 666 #else 667 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \ 668 iter, category, concept, value_type, reference, pointer, difference_type) \ 669 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \ 670 iter, category, value_type, reference, pointer, difference_type) 671 #endif 672 673 #endif 674 675 #endif 676