Merge pull request #28 from ericniebler/develop

make range_iterator, range_difference, and range_size SFINAE-friendly, r...
This commit is contained in:
neilgroves
2015-04-14 09:26:35 +01:00
3 changed files with 64 additions and 39 deletions

View File

@ -15,20 +15,37 @@
# pragma once # pragma once
#endif #endif
#include <boost/mpl/and.hpp>
#include <boost/range/config.hpp> #include <boost/range/config.hpp>
#include <boost/range/iterator.hpp> #include <boost/range/iterator.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/iterator/iterator_traits.hpp> #include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_reference.hpp>
namespace boost namespace boost
{ {
namespace range_detail
{
template< class T, class Enabler=void >
struct range_difference
{ };
template< class T >
struct range_difference<
T,
BOOST_DEDUCED_TYPENAME ::boost::enable_if_c<
has_type<range_iterator<T> >::value
>::type
>
: iterator_difference<
BOOST_DEDUCED_TYPENAME range_iterator<T>::type
>
{ };
}
template< class T > template< class T >
struct range_difference struct range_difference
: iterator_difference< : range_detail::range_difference<BOOST_DEDUCED_TYPENAME remove_reference<T>::type>
BOOST_DEDUCED_TYPENAME range_iterator<
BOOST_DEDUCED_TYPENAME remove_reference<T>::type
>::type
>
{ }; { };
} }

View File

@ -46,31 +46,29 @@ namespace boost
}; };
} }
#endif
template< typename C, typename Enabler=void > template< typename C, typename Enabler=void >
struct range_iterator struct range_iterator
{ {
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
typedef BOOST_RANGE_DEDUCED_TYPENAME typedef BOOST_RANGE_DEDUCED_TYPENAME
range_detail_vc7_1::range_iterator<C>::type type; range_detail_vc7_1::range_iterator<C>::type type;
#else
private:
typedef typename remove_reference<C>::type param_t;
public:
typedef typename mpl::eval_if_c<
is_const<param_t>::value,
range_const_iterator<typename remove_const<param_t>::type>,
range_mutable_iterator<param_t>
>::type type;
#endif
}; };
#else
template< typename C, typename Enabler=void >
struct range_iterator
: mpl::if_c<
is_const<typename remove_reference<C>::type>::value,
range_const_iterator<typename remove_const<typename remove_reference<C>::type>::type>,
range_mutable_iterator<typename remove_reference<C>::type>
>::type
{
};
#endif
} // namespace boost } // namespace boost
#endif #endif

View File

@ -18,6 +18,7 @@
#include <boost/range/config.hpp> #include <boost/range/config.hpp>
#include <boost/range/difference_type.hpp> #include <boost/range/difference_type.hpp>
#include <boost/range/concepts.hpp> #include <boost/range/concepts.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/type_traits/make_unsigned.hpp> #include <boost/type_traits/make_unsigned.hpp>
@ -51,7 +52,7 @@ namespace boost
}; };
template<typename C, typename Enabler=void> template<typename C, typename Enabler=void>
struct range_size struct range_size_
{ {
typedef BOOST_DEDUCED_TYPENAME make_unsigned< typedef BOOST_DEDUCED_TYPENAME make_unsigned<
BOOST_DEDUCED_TYPENAME range_difference<C>::type BOOST_DEDUCED_TYPENAME range_difference<C>::type
@ -59,7 +60,7 @@ namespace boost
}; };
template<typename C> template<typename C>
struct range_size< struct range_size_<
C, C,
BOOST_DEDUCED_TYPENAME ::boost::enable_if<has_size_type<C>, void>::type BOOST_DEDUCED_TYPENAME ::boost::enable_if<has_size_type<C>, void>::type
> >
@ -67,29 +68,38 @@ namespace boost
typedef BOOST_DEDUCED_TYPENAME C::size_type type; typedef BOOST_DEDUCED_TYPENAME C::size_type type;
}; };
} template<typename C, typename Enabler=void>
struct range_size
{ };
template< class T > template<typename C>
struct range_size : struct range_size<
detail::range_size<T> C,
{ BOOST_DEDUCED_TYPENAME ::boost::enable_if_c<
range_detail::has_type< range_iterator<C> >::value
>::type
>
: range_size_<C>
{
// Very strange things happen on some compilers that have the range concept // Very strange things happen on some compilers that have the range concept
// asserts disabled. This preprocessor condition is clearly redundant on a // asserts disabled. This preprocessor condition is clearly redundant on a
// working compiler but is vital for at least some compilers such as clang 4.2 // working compiler but is vital for at least some compilers such as clang 4.2
// but only on the Mac! // but only on the Mac!
#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1 #if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1
BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<T>)); BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<C>));
#endif #endif
}; };
}
template< class T > template< class T >
struct range_size<const T > struct range_size :
: detail::range_size<T> detail::range_size<T>
{ { };
#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1
BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<T>)); template< class T >
#endif struct range_size<const T > :
}; detail::range_size<T>
{ };
} // namespace boost } // namespace boost