// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify, // sell and distribute this software is granted provided this // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. #ifndef BOOST_ITERATOR_CONCEPTS_HPP #define BOOST_ITERATOR_CONCEPTS_HPP // Revision History // 26 Apr 2003 thw // Adapted to new iterator concepts // 22 Nov 2002 Thomas Witt // Added interoperable concept. #include #include #include #include #include #include #include #include // Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. #include // Use boost/limits to work around missing limits headers on some compilers #include #include namespace boost_concepts { // Used a different namespace here (instead of "boost") so that the // concept descriptions do not take for granted the names in // namespace boost. // We use this in place of STATIC_ASSERT((is_convertible<...>)) // because some compilers (CWPro7.x) can't detect convertibility. // // Of course, that just gets us a different error at the moment with // some tests, since new iterator category deduction still depends // on convertibility detection. We might need some specializations // to support this compiler. template struct static_assert_base_and_derived { static_assert_base_and_derived(Target* = (Source*)0) {} }; //=========================================================================== // Iterator Access Concepts template class ReadableIteratorConcept { public: typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::value_type value_type; typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::reference reference; typedef BOOST_DEDUCED_TYPENAME ::boost::access_category::type access_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); reference r = *i; // or perhaps read(x) value_type v(r); boost::ignore_unused_variable_warning(v); } Iterator i; }; template class WritableIteratorConcept { public: typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); *i = v; // a good alternative could be something like write(x, v) } ValueType v; Iterator i; }; template class SwappableIteratorConcept { public: typedef typename boost::access_category::type access_category; void constraints() { BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); std::iter_swap(i1, i2); } Iterator i1; Iterator i2; }; template class ReadableLvalueIteratorConcept { public: typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::reference reference; typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< ReadableIteratorConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); typedef boost::mpl::or_< boost::is_same, boost::is_same > correct_reference; BOOST_STATIC_ASSERT(correct_reference::value); reference v = *i; boost::ignore_unused_variable_warning(v); } Iterator i; }; template class WritableLvalueIteratorConcept { public: typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::reference reference; typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< ReadableLvalueIteratorConcept >(); boost::function_requires< WritableIteratorConcept >(); boost::function_requires< SwappableIteratorConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); } }; //=========================================================================== // Iterator Traversal Concepts template class IncrementableIteratorConcept { public: typedef typename boost::traversal_category::type traversal_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); ++i; (void)i++; } Iterator i; }; template class SinglePassIteratorConcept { public: typedef typename boost::traversal_category::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< IncrementableIteratorConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); } }; template class ForwardTraversalConcept { public: typedef typename boost::traversal_category::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< SinglePassIteratorConcept >(); typedef boost::mpl::and_< boost::is_integral, boost::mpl::bool_< std::numeric_limits::is_signed > > difference_type_is_signed_integral; BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); } }; template class BidirectionalTraversalConcept { public: typedef typename boost::traversal_category::type traversal_category; void constraints() { boost::function_requires< ForwardTraversalConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); --i; (void)i--; } Iterator i; }; template class RandomAccessTraversalConcept { public: typedef typename boost::traversal_category::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< BidirectionalTraversalConcept >(); BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); i += n; i = i + n; i = n + i; i -= n; i = i - n; n = i - j; } difference_type n; Iterator i, j; }; //=========================================================================== // Iterator Interoperability Concept namespace detail { template struct Operations; template <> struct Operations { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { // no interoperability constraints } }; template <> struct Operations { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { Operations::constraints(i1, i2); i1 == i2; i1 != i2; i2 == i1; i2 != i1; } }; template <> struct Operations { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { Operations::constraints(i1, i2); } }; template <> struct Operations { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { Operations::constraints(i1, i2); } }; template <> struct Operations { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { Operations::constraints(i1, i2); i1 < i2; i1 <= i2; i1 > i2; i1 >= i2; i1 - i2; i2 < i1; i2 <= i1; i2 > i1; i2 >= i1; i2 - i1; } }; } // namespace detail template class InteroperableConcept { public: typedef typename boost::traversal_category::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; typedef typename boost::traversal_category::type const_traversal_category; typedef typename boost::detail::iterator_traits::difference_type const_difference_type; void constraints() { BOOST_STATIC_ASSERT((boost::is_same< difference_type, const_difference_type>::value)); BOOST_STATIC_ASSERT((boost::is_same< traversal_category, const_traversal_category>::value)); // ToDo check what the std really requires // detail::Operations::constraints(i, ci); ci = i; } Iterator i; ConstIterator ci; }; } // namespace boost_concepts #endif // BOOST_ITERATOR_CONCEPTS_HPP