//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// std::filter_view::<iterator>::difference_type
// std::filter_view::<iterator>::value_type
// std::filter_view::<iterator>::iterator_category
// std::filter_view::<iterator>::iterator_concept
#include <ranges>
#include <type_traits>
#include "test_iterators.h"
#include "../types.h"
template <typename T>
concept HasIteratorCategory = requires {
typename T::iterator_category;
};
template <class Iterator>
using FilterViewFor = std::ranges::filter_view<
minimal_view<Iterator, sentinel_wrapper<Iterator>>,
AlwaysTrue
>;
template <class Iterator>
using FilterIteratorFor = std::ranges::iterator_t<FilterViewFor<Iterator>>;
struct ForwardIteratorWithInputCategory {
using difference_type = int;
using value_type = int;
using iterator_category = std::input_iterator_tag;
using iterator_concept = std::forward_iterator_tag;
ForwardIteratorWithInputCategory();
ForwardIteratorWithInputCategory& operator++();
ForwardIteratorWithInputCategory operator++(int);
int& operator*() const;
friend bool operator==(ForwardIteratorWithInputCategory, ForwardIteratorWithInputCategory);
};
static_assert(std::forward_iterator<ForwardIteratorWithInputCategory>);
void f() {
// Check that value_type is range_value_t and difference_type is range_difference_t
{
auto test = []<class Iterator> {
using FilterView = FilterViewFor<Iterator>;
using FilterIterator = FilterIteratorFor<Iterator>;
static_assert(std::is_same_v<typename FilterIterator::value_type, std::ranges::range_value_t<FilterView>>);
static_assert(std::is_same_v<typename FilterIterator::difference_type, std::ranges::range_difference_t<FilterView>>);
};
test.operator()<cpp17_input_iterator<int*>>();
test.operator()<cpp20_input_iterator<int*>>();
test.operator()<forward_iterator<int*>>();
test.operator()<bidirectional_iterator<int*>>();
test.operator()<random_access_iterator<int*>>();
test.operator()<contiguous_iterator<int*>>();
test.operator()<int*>();
}
// Check iterator_concept for various categories of ranges
{
static_assert(std::is_same_v<FilterIteratorFor<cpp17_input_iterator<int*>>::iterator_concept, std::input_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<cpp20_input_iterator<int*>>::iterator_concept, std::input_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<ForwardIteratorWithInputCategory>::iterator_concept, std::forward_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<forward_iterator<int*>>::iterator_concept, std::forward_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<bidirectional_iterator<int*>>::iterator_concept, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<random_access_iterator<int*>>::iterator_concept, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<contiguous_iterator<int*>>::iterator_concept, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<int*>::iterator_concept, std::bidirectional_iterator_tag>);
}
// Check iterator_category for various categories of ranges
{
static_assert(!HasIteratorCategory<FilterIteratorFor<cpp17_input_iterator<int*>>>);
static_assert(!HasIteratorCategory<FilterIteratorFor<cpp20_input_iterator<int*>>>);
static_assert(std::is_same_v<FilterIteratorFor<ForwardIteratorWithInputCategory>::iterator_category, std::input_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<forward_iterator<int*>>::iterator_category, std::forward_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<bidirectional_iterator<int*>>::iterator_category, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<random_access_iterator<int*>>::iterator_category, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<contiguous_iterator<int*>>::iterator_category, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<FilterIteratorFor<int*>::iterator_category, std::bidirectional_iterator_tag>);
}
}