// 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 struct basic_input_iter : boost::stl_interfaces:: iterator_interface { 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; using base_type::operator++; private: int * it_; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( basic_input_iter, std::input_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( basic_input_iter, std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t) template struct input_iter : boost::stl_interfaces::iterator_interface< input_iter, 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< input_iter, 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) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( input_iter, std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t) 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< proxy_input_iter, 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< proxy_input_iter, 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) 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) 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::v1::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< data_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::v1::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::v1::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< size_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::v1::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::v1::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< back_t_, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::v1::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::v1::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< index_operator_t, subrange< basic_input_iter, basic_input_iter, boost::stl_interfaces::v1::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; std::copy(first, last, ints_copy.begin()); 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); std::equal(first, last, first_copy, last_copy); } { int_input first(ints.data()); int_input last(ints.data() + ints.size()); while (first != last) first++; } { { std::array ints_copy; int_input first(ints.data()); int_input last(ints.data() + ints.size()); std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { std::array, 10> pairs_copy; pair_input first(pairs.data()); pair_input last(pairs.data() + pairs.size()); std::copy(first, last, pairs_copy.begin()); 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()); std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { std::array, 10> pairs_copy; const_pair_input first(pairs.data()); const_pair_input last(pairs.data() + pairs.size()); std::copy(first, last, pairs_copy.begin()); 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; std::copy(r.begin(), r.end(), ints_copy.begin()); BOOST_TEST(ints_copy == ints); BOOST_TEST(empty.begin() == empty.end()); } // empty/op bool { BOOST_TEST(!r.empty()); BOOST_TEST(r); BOOST_TEST(empty.empty()); BOOST_TEST(!empty); auto const cr = r; BOOST_TEST(!cr.empty()); BOOST_TEST(cr); auto const cempty = empty; BOOST_TEST(cempty.empty()); BOOST_TEST(!cempty); } // front/back { BOOST_TEST(r.front() == 0); auto const cr = r; BOOST_TEST(cr.front() == 0); } } return boost::report_errors(); }