// Copyright (C) 2019 T. Zachary Laine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include "ill_formed.hpp" #include #include #include #include #include struct basic_input_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_input_iter, #endif std::input_iterator_tag, int> { basic_input_iter() : it_(nullptr) {} basic_input_iter(int * it) : it_(it) {} int & operator*() const noexcept { return *it_; } basic_input_iter & operator++() noexcept { ++it_; return *this; } friend bool operator==(basic_input_iter lhs, basic_input_iter rhs) noexcept { return lhs.it_ == rhs.it_; } using base_type = boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_input_iter, #endif std::input_iterator_tag, int>; using base_type::operator++; private: int * it_; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( basic_input_iter, std::input_iterator) #if __cplusplus < 202002L BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( basic_input_iter, std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t) #endif template struct input_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS input_iter, #endif std::input_iterator_tag, ValueType> { input_iter() : it_(nullptr) {} input_iter(ValueType * it) : it_(it) {} template< typename ValueType2, typename E = std::enable_if_t< std::is_convertible::value>> input_iter(input_iter it) : it_(it.it_) {} ValueType & operator*() const noexcept { return *it_; } input_iter & operator++() noexcept { ++it_; return *this; } friend bool operator==(input_iter lhs, input_iter rhs) noexcept { return lhs.it_ == rhs.it_; } using base_type = boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS input_iter, #endif std::input_iterator_tag, ValueType>; using base_type::operator++; private: ValueType * it_; template friend struct input_iter; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(input_iter, std::input_iterator) #if __cplusplus < 202002L BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( input_iter, std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t) #endif using int_input = input_iter; using const_int_input = input_iter; using pair_input = input_iter>; using const_pair_input = input_iter const>; template struct proxy_input_iter : boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS proxy_input_iter, #endif std::input_iterator_tag, ValueType> { proxy_input_iter() : it_(nullptr) {} proxy_input_iter(ValueType * it) : it_(it) {} template< typename ValueType2, typename E = std::enable_if_t< std::is_convertible::value>> proxy_input_iter(proxy_input_iter it) : it_(it.it_) {} ValueType operator*() const noexcept { return *it_; } proxy_input_iter & operator++() noexcept { ++it_; return *this; } friend bool operator==(proxy_input_iter lhs, proxy_input_iter rhs) noexcept { return lhs.it_ == rhs.it_; } using base_type = boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS proxy_input_iter, #endif std::input_iterator_tag, ValueType>; using base_type::operator++; private: ValueType * it_; template friend struct proxy_input_iter; }; using int_pair = std::pair; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( proxy_input_iter, std::input_iterator) #if __cplusplus < 202002L BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( proxy_input_iter, std::input_iterator_tag, std::input_iterator_tag, int_pair, int_pair, boost::stl_interfaces::proxy_arrow_result, std::ptrdiff_t) #endif std::array ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; std::array, 10> pairs = {{ {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, }}; //////////////////// // view_interface // //////////////////// #include "view_tests.hpp" template using data_t = decltype(std::declval().data()); static_assert( ill_formed< data_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< data_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); template using size_t_ = decltype(std::declval().size()); static_assert( ill_formed< size_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< size_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); template using back_t_ = decltype(std::declval().back()); static_assert( ill_formed< back_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< back_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); template using index_operator_t = decltype(std::declval()[0]); static_assert( ill_formed< index_operator_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< index_operator_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); int main() { { basic_input_iter first(ints.data()); basic_input_iter last(ints.data() + ints.size()); { std::array ints_copy; #if __cplusplus < 202002L std::copy(first, last, ints_copy.begin()); #else std::ranges::copy(first, last, ints_copy.begin()); #endif BOOST_TEST(ints_copy == ints); } } { int_input first(ints.data()); int_input last(ints.data() + ints.size()); const_int_input first_copy(first); const_int_input last_copy(last); #if __cplusplus < 202002L std::equal(first, last, first_copy, last_copy); #else std::ranges::equal(first, last, first_copy, last_copy); #endif } { { std::array ints_copy; int_input first(ints.data()); int_input last(ints.data() + ints.size()); #if __cplusplus < 202002L std::copy(first, last, ints_copy.begin()); #else std::ranges::copy(first, last, ints_copy.begin()); #endif BOOST_TEST(ints_copy == ints); } { std::array, 10> pairs_copy; pair_input first(pairs.data()); pair_input last(pairs.data() + pairs.size()); #if __cplusplus < 202002L std::copy(first, last, pairs_copy.begin()); #else std::ranges::copy(first, last, pairs_copy.begin()); #endif BOOST_TEST(pairs_copy == pairs); } { std::array firsts_copy; pair_input first(pairs.data()); pair_input last(pairs.data() + pairs.size()); for (auto out = firsts_copy.begin(); first != last; ++first) { *out++ = (*first).first; } BOOST_TEST(firsts_copy == ints); } { std::array firsts_copy; proxy_input_iter> first(pairs.data()); proxy_input_iter> last(pairs.data() + pairs.size()); for (auto out = firsts_copy.begin(); first != last; ++first) { *out++ = (*first).first; } BOOST_TEST(firsts_copy == ints); } } { { std::array ints_copy; const_int_input first(ints.data()); const_int_input last(ints.data() + ints.size()); #if __cplusplus < 202002L std::copy(first, last, ints_copy.begin()); #else std::ranges::copy(first, last, ints_copy.begin()); #endif BOOST_TEST(ints_copy == ints); } { std::array, 10> pairs_copy; const_pair_input first(pairs.data()); const_pair_input last(pairs.data() + pairs.size()); #if __cplusplus < 202002L std::copy(first, last, pairs_copy.begin()); #else std::ranges::copy(first, last, pairs_copy.begin()); #endif BOOST_TEST(pairs_copy == pairs); } { std::array firsts_copy; const_pair_input first(pairs.data()); const_pair_input last(pairs.data() + pairs.size()); for (auto out = firsts_copy.begin(); first != last; ++first) { *out++ = (*first).first; } BOOST_TEST(firsts_copy == ints); } { std::array firsts_copy; proxy_input_iter const> first(pairs.data()); proxy_input_iter const> last( pairs.data() + pairs.size()); for (auto out = firsts_copy.begin(); first != last; ++first) { *out++ = (*first).first; } BOOST_TEST(firsts_copy == ints); } } { basic_input_iter first(ints.data()); basic_input_iter last(ints.data() + ints.size()); auto r = range( first, last); auto empty = range( first, first); // range begin/end { std::array ints_copy; #if __cplusplus < 202002L std::copy(r.begin(), r.end(), ints_copy.begin()); #else std::ranges::copy(r.begin(), r.end(), ints_copy.begin()); #endif BOOST_TEST(ints_copy == ints); BOOST_TEST(empty.begin() == empty.end()); } } return boost::report_errors(); }