Header file range/v3/action/concepts.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/range_concepts.hpp>

#include <range/v3/range_traits.hpp>

#include <range/v3/utility/functional.hpp>

namespace ranges
{
    inline namespace v3
    {
        namespace detail
        {
            template <typename T>
            struct movable_input_iterator
            : std::iterator<std::input_iterator_tag, T, std::ptrdiff_t, T *, T &&>
            {
                movable_input_iterator() = default;
                
                movable_input_iterator& operator++();
                
                movable_input_iterator operator++(int);
                
                bool operator==(movable_input_iterator const&) const;
                
                bool operator!=(movable_input_iterator const&) const;
                
                T&& operator*() const;
            };
        }
        
        namespace concepts
        {
            struct SemiContainer
            : refines<struct ranges::v3::concepts::ForwardRange>
            {
                template <typename T>
                decltype(concepts::valid_expr(concepts::model_of<DefaultConstructible, uncvref_t<T>>(), concepts::model_of<Movable, uncvref_t<T>>(), concepts::is_false(is_view<T>()))) requires_(T&&);
            };
            
            struct Container
            : refines<struct ranges::v3::concepts::SemiContainer>
            {
                template <typename T, typename I = detail::movable_input_iterator<range_value_t<T>>>
                decltype(concepts::valid_expr(concepts::model_of<Constructible, uncvref_t<T>, I, I>())) requires_(T&&);
            };
        }
        
        template <typename T>
        using SemiContainer = concepts::models<concepts::SemiContainer, T>;
        
        template <typename T>
        using Container = concepts::models<concepts::Container, T>;
        
        namespace concepts
        {
            struct Reservable
            : refines<struct ranges::v3::concepts::Container>
            {
                template <typename C>
                using size_type = decltype(std::declval<const C&>().size());
                
                template <typename C, typename S = size_type<C>>
                decltype(concepts::valid_expr(concepts::model_of<Integral, S>(), ((void)c.reserve(s), 42))) requires_(C&& c, S&& s = S{});
            };
            
            struct ReserveAndAssignable
            : refines<struct ranges::v3::concepts::Reservable (_1), struct ranges::v3::concepts::InputIterator (_2)>
            {
                template <typename C, typename I>
                decltype(concepts::valid_expr(((void)c.assign(i, i), 42))) requires_(C&& c, I&& i);
            };
        }
        
        template <typename C>
        using Reservable = concepts::models<concepts::Reservable, C>;
        
        template <typename C, typename I>
        using ReserveAndAssignable = concepts::models<concepts::ReserveAndAssignable, C, I>;
        
        template <typename C>
        using RandomAccessReservable = meta::strict_and<Reservable<C>, RandomAccessRange<C>>;
        
        namespace detail
        {
            template <typename T, int _concept_requires_122 = 42, typename std::enable_if<(_concept_requires_122==43)||(Container<T>()), int>::type=0>
            std::true_type is_lvalue_container_like(T&);
            
            template <typename T, int _concept_requires_125 = 42, typename std::enable_if<(_concept_requires_125==43)||(Container<T>()), int>::type=0>
            std::true_type is_lvalue_container_like(reference_wrapper<T>);
            
            template <typename T, int _concept_requires_128 = 42, typename std::enable_if<(_concept_requires_128==43)||(Container<T>()), int>::type=0>
            std::true_type is_lvalue_container_like(std::reference_wrapper<T>);
        }
        
        namespace concepts
        {
            struct LvalueContainerLike
            : refines<struct ranges::v3::concepts::ForwardRange>
            {
                template <typename T>
                decltype(concepts::valid_expr(detail::is_lvalue_container_like(std::forward<T>(t)))) requires_(T&& t);
            };
        }
        
        template <typename T>
        using LvalueContainerLike = concepts::models<concepts::LvalueContainerLike, T>;
    }
}