Header file range/v3/utility/associated_types.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

namespace ranges
{
    inline namespace v3
    {
        template <typename T, typename Enable>
        struct difference_type;
        
        template <>
        struct difference_type<std::nullptr_t>
        {
            using type = std::ptrdiff_t;
        };
        
        template <typename T>
        struct difference_type<T*>
        : meta::lazy::if_<std::is_object<T>, std::ptrdiff_t>
        {};
        
        template <typename T>
        struct difference_type<T, meta::if_<std::is_array<T>>>
        : difference_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct difference_type<T const>
        : difference_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct difference_type<T volatile>
        : difference_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct difference_type<T const volatile>
        : difference_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct difference_type<T, meta::void_<typename T::difference_type>>
        {
            using type = typename T::difference_type;
        };
        
        template <typename T>
        struct difference_type<T, meta::if_<std::is_integral<T>>>
        : std::make_signed<decltype(std::declval<T>() - std::declval<T>())>
        {};
        
        template <typename T>
        struct size_type;
        
        template <typename T, typename Enable>
        struct value_type;
        
        template <typename T>
        struct value_type<T*>
        : meta::lazy::if_<std::is_object<T>, meta::_t<std::remove_cv<T> > >
        {};
        
        template <typename T>
        struct value_type<T, meta::if_<std::is_array<T>>>
        : value_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct value_type<T const>
        : value_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct value_type<T volatile>
        : value_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct value_type<T const volatile>
        : value_type<detail::decay_t<T> >
        {};
        
        template <typename T>
        struct value_type<T, meta::void_<typename T::value_type>>
        : meta::lazy::if_<std::is_object<typename T::value_type>, typename T::value_type>
        {};
        
        template <typename T>
        struct value_type<T, meta::void_<typename T::element_type>>
        : meta::lazy::if_<std::is_object<typename T::element_type>, typename T::element_type>
        {};
        
        template <typename T>
        struct value_type<T, meta::if_<std::is_base_of<std::ios_base, T>>>
        {
            using type = typename T::char_type;
        };
        
        template <typename S, typename I>
        struct disable_sized_sentinel
        : std::false_type
        {};
    }
}

Class template ranges::v3::difference_type<T, Enable>

template <typename T, typename Enable>
struct difference_type{};

/////////////////////////////////////////////////////////////////////////////////////


Class template ranges::v3::size_type<T>

template <typename T>
struct size_type
: meta::lazy::let<std::make_unsigned<meta::lazy::_t<difference_type<T> > > >
{};

/////////////////////////////////////////////////////////////////////////////////////


Class template ranges::v3::value_type<T, Enable>

template <typename T, typename Enable>
struct value_type{};

/////////////////////////////////////////////////////////////////////////////////////