// 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 #include #include struct basic_random_access_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_random_access_iter, #endif std::random_access_iterator_tag, int> { basic_random_access_iter() {} basic_random_access_iter(int * it) : it_(it) {} int & operator*() const { return *it_; } basic_random_access_iter & operator+=(std::ptrdiff_t i) { it_ += i; return *this; } friend std::ptrdiff_t operator-( basic_random_access_iter lhs, basic_random_access_iter rhs) noexcept { return lhs.it_ - rhs.it_; } private: int * it_; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( basic_random_access_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( basic_random_access_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int &, int *, std::ptrdiff_t) static_assert( boost::stl_interfaces::v1::v1_dtl:: plus_eq::value, ""); // This is here explicitly to check that the nested typedefs make it into the // derived iterator type when boost::stl_interfaces::iterator_interface<...> // is a dependent type. template struct basic_random_access_iter_dependent : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_random_access_iter_dependent, #endif std::random_access_iterator_tag, ValueType> { basic_random_access_iter_dependent() {} basic_random_access_iter_dependent(ValueType * it) : it_(it) {} ValueType & operator*() const { return *it_; } basic_random_access_iter_dependent & operator+=(std::ptrdiff_t i) { it_ += i; return *this; } friend std::ptrdiff_t operator-( basic_random_access_iter_dependent lhs, basic_random_access_iter_dependent rhs) noexcept { return lhs.it_ - rhs.it_; } private: ValueType * it_; }; using basic_random_access_iter_dependent_category = basic_random_access_iter_dependent::iterator_category; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( basic_random_access_iter_dependent, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( basic_random_access_iter_dependent, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int &, int *, std::ptrdiff_t) struct basic_adapted_random_access_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_adapted_random_access_iter, #endif std::random_access_iterator_tag, int> { basic_adapted_random_access_iter() {} basic_adapted_random_access_iter(int * it) : it_(it) {} private: friend boost::stl_interfaces::access; int *& base_reference() noexcept { return it_; } int * base_reference() const noexcept { return it_; } int * it_; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( basic_adapted_random_access_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( basic_adapted_random_access_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int &, int *, std::ptrdiff_t) template struct adapted_random_access_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS adapted_random_access_iter, #endif std::random_access_iterator_tag, ValueType> { adapted_random_access_iter() {} adapted_random_access_iter(ValueType * it) : it_(it) {} template< typename ValueType2, typename Enable = std::enable_if_t< std::is_convertible::value>> adapted_random_access_iter(adapted_random_access_iter other) : it_(other.it_) {} template friend struct adapted_random_access_iter; private: friend boost::stl_interfaces::access; ValueType *& base_reference() noexcept { return it_; } ValueType * base_reference() const noexcept { return it_; } ValueType * it_; }; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( adapted_random_access_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( adapted_random_access_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int &, int *, std::ptrdiff_t) BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( adapted_random_access_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( adapted_random_access_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int const &, int const *, std::ptrdiff_t) template struct random_access_iter : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS random_access_iter, #endif std::random_access_iterator_tag, ValueType> { random_access_iter() {} random_access_iter(ValueType * it) : it_(it) {} template< typename ValueType2, typename E = std::enable_if_t< std::is_convertible::value>> random_access_iter(random_access_iter it) : it_(it.it_) {} ValueType & operator*() const { return *it_; } random_access_iter & operator+=(std::ptrdiff_t i) { it_ += i; return *this; } friend std::ptrdiff_t operator-(random_access_iter lhs, random_access_iter rhs) noexcept { return lhs.it_ - rhs.it_; } private: ValueType * it_; template friend struct random_access_iter; }; using random_access = random_access_iter; using const_random_access = random_access_iter; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( random_access, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( random_access, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int &, int *, std::ptrdiff_t) BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( const_random_access, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( const_random_access, std::random_access_iterator_tag, std::random_access_iterator_tag, int, int const &, int const *, std::ptrdiff_t) struct zip_iter : boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS zip_iter, #endif std::random_access_iterator_tag, std::tuple, std::tuple> { zip_iter() : it1_(nullptr), it2_(nullptr) {} zip_iter(int * it1, int * it2) : it1_(it1), it2_(it2) {} std::tuple operator*() const { return std::tuple{*it1_, *it2_}; } zip_iter & operator+=(std::ptrdiff_t i) { it1_ += i; it2_ += i; return *this; } friend std::ptrdiff_t operator-(zip_iter lhs, zip_iter rhs) noexcept { return lhs.it1_ - rhs.it1_; } private: int * it1_; int * it2_; }; using int_pair = std::tuple; using int_refs_pair = std::tuple; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( zip_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( zip_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int_pair, int_refs_pair, boost::stl_interfaces::proxy_arrow_result, std::ptrdiff_t) struct int_t { int value_; bool operator==(int_t other) const { return value_ == other.value_; } bool operator!=(int_t other) const { return value_ != other.value_; } bool operator<(int_t other) const { return value_ < other.value_; } bool operator==(int other) const { return value_ == other; } bool operator!=(int other) const { return value_ != other; } bool operator<(int other) const { return value_ < other; } friend bool operator==(int lhs, int_t rhs) { return lhs == rhs.value_; } friend bool operator!=(int lhs, int_t rhs) { return lhs != rhs.value_; } friend bool operator<(int lhs, int_t rhs) { return lhs < rhs.value_; } }; struct udt_zip_iter : boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS udt_zip_iter, #endif std::random_access_iterator_tag, std::tuple, std::tuple> { udt_zip_iter() : it1_(nullptr), it2_(nullptr) {} udt_zip_iter(int_t * it1, int * it2) : it1_(it1), it2_(it2) {} std::tuple operator*() const { return std::tuple{*it1_, *it2_}; } udt_zip_iter & operator+=(std::ptrdiff_t i) { it1_ += i; it2_ += i; return *this; } friend std::ptrdiff_t operator-(udt_zip_iter lhs, udt_zip_iter rhs) noexcept { return lhs.it1_ - rhs.it1_; } private: int_t * it1_; int * it2_; }; using int_t_int_pair = std::tuple; using int_t_int_refs_pair = std::tuple; BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT( udt_zip_iter, std::random_access_iterator) BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( udt_zip_iter, std::random_access_iterator_tag, std::random_access_iterator_tag, int_t_int_pair, int_t_int_refs_pair, boost::stl_interfaces::proxy_arrow_result, std::ptrdiff_t) namespace std { // Required for std::sort to work with zip_iter. If zip_iter::reference // were not a std::tuple with builtin types as its template parameters, we // could have put this in another namespace. void swap(zip_iter::reference && lhs, zip_iter::reference && rhs) { using std::swap; swap(std::get<0>(lhs), std::get<0>(rhs)); swap(std::get<1>(lhs), std::get<1>(rhs)); } } void swap(udt_zip_iter::reference && lhs, udt_zip_iter::reference && rhs) { using std::swap; swap(std::get<0>(lhs), std::get<0>(rhs)); swap(std::get<1>(lhs), std::get<1>(rhs)); } std::array ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; std::array ones = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; std::array, 10> tuples = {{ {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, }}; std::array udts = { {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}}}; std::array, 10> udt_tuples = {{ std::tuple{{0}, 1}, std::tuple{{1}, 1}, std::tuple{{2}, 1}, std::tuple{{3}, 1}, std::tuple{{4}, 1}, std::tuple{{5}, 1}, std::tuple{{6}, 1}, std::tuple{{7}, 1}, std::tuple{{8}, 1}, std::tuple{{9}, 1}, }}; //////////////////// // view_interface // //////////////////// #include "view_tests.hpp" #if !BOOST_STL_INTERFACES_USE_CONCEPTS template using data_t = decltype(std::declval().data()); static_assert( ill_formed< data_t, subrange< basic_random_access_iter, basic_random_access_iter, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< data_t, subrange< basic_random_access_iter, basic_random_access_iter, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); template using back_t = decltype(std::declval().back()); static_assert( ill_formed< back_t, subrange< int *, int const *, boost::stl_interfaces::element_layout::discontiguous>>::value, ""); static_assert( ill_formed< back_t, subrange< int *, int const *, boost::stl_interfaces::element_layout::discontiguous> const>:: value, ""); #endif int main() { { basic_random_access_iter first(ints.data()); basic_random_access_iter last(ints.data() + ints.size()); BOOST_TEST(*first == 0); BOOST_TEST(*(first + 1) == 1); BOOST_TEST(*(first + 2) == 2); BOOST_TEST(*(1 + first) == 1); BOOST_TEST(*(2 + first) == 2); BOOST_TEST(first[0] == 0); BOOST_TEST(first[1] == 1); BOOST_TEST(first[2] == 2); BOOST_TEST(*(last - 1) == 9); BOOST_TEST(*(last - 2) == 8); BOOST_TEST(*(last - 3) == 7); BOOST_TEST(last[-1] == 9); BOOST_TEST(last[-2] == 8); BOOST_TEST(last[-3] == 7); BOOST_TEST(last - first == 10); BOOST_TEST(first == first); BOOST_TEST(first != last); BOOST_TEST(first < last); BOOST_TEST(first <= last); BOOST_TEST(first <= first); BOOST_TEST(last > first); BOOST_TEST(last >= first); BOOST_TEST(last >= last); { auto first_copy = first; first_copy += 10; BOOST_TEST(first_copy == last); } { auto last_copy = last; last_copy -= 10; BOOST_TEST(last_copy == first); } } { { std::array ints_copy; basic_random_access_iter first(ints.data()); basic_random_access_iter last(ints.data() + ints.size()); std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { std::array ints_copy; basic_random_access_iter first(ints.data()); basic_random_access_iter last(ints.data() + ints.size()); std::copy( std::make_reverse_iterator(last), std::make_reverse_iterator(first), ints_copy.begin()); std::reverse(ints_copy.begin(), ints_copy.end()); BOOST_TEST(ints_copy == ints); } { std::array iota_ints; basic_random_access_iter first(iota_ints.data()); basic_random_access_iter last(iota_ints.data() + iota_ints.size()); std::iota(first, last, 0); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; basic_random_access_iter first(iota_ints.data()); basic_random_access_iter last(iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::reverse(iota_ints.begin(), iota_ints.end()); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; basic_random_access_iter first(iota_ints.data()); basic_random_access_iter last(iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::sort(first, last); BOOST_TEST(iota_ints == ints); } } { basic_adapted_random_access_iter first(ints.data()); basic_adapted_random_access_iter last(ints.data() + ints.size()); BOOST_TEST(*first == 0); BOOST_TEST(*(first + 1) == 1); BOOST_TEST(*(first + 2) == 2); BOOST_TEST(*(1 + first) == 1); BOOST_TEST(*(2 + first) == 2); BOOST_TEST(first[0] == 0); BOOST_TEST(first[1] == 1); BOOST_TEST(first[2] == 2); BOOST_TEST(*(last - 1) == 9); BOOST_TEST(*(last - 2) == 8); BOOST_TEST(*(last - 3) == 7); BOOST_TEST(last[-1] == 9); BOOST_TEST(last[-2] == 8); BOOST_TEST(last[-3] == 7); BOOST_TEST(last - first == 10); BOOST_TEST(first == first); BOOST_TEST(first != last); BOOST_TEST(first < last); BOOST_TEST(first <= last); BOOST_TEST(first <= first); BOOST_TEST(last > first); BOOST_TEST(last >= first); BOOST_TEST(last >= last); { auto first_copy = first; first_copy += 10; BOOST_TEST(first_copy == last); } { auto last_copy = last; last_copy -= 10; BOOST_TEST(last_copy == first); } } { { std::array ints_copy; basic_adapted_random_access_iter first(ints.data()); basic_adapted_random_access_iter last(ints.data() + ints.size()); std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { std::array ints_copy; basic_adapted_random_access_iter first(ints.data()); basic_adapted_random_access_iter last(ints.data() + ints.size()); std::copy( std::make_reverse_iterator(last), std::make_reverse_iterator(first), ints_copy.begin()); std::reverse(ints_copy.begin(), ints_copy.end()); BOOST_TEST(ints_copy == ints); } { std::array iota_ints; basic_adapted_random_access_iter first(iota_ints.data()); basic_adapted_random_access_iter last( iota_ints.data() + iota_ints.size()); std::iota(first, last, 0); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; basic_adapted_random_access_iter first(iota_ints.data()); basic_adapted_random_access_iter last( iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::reverse(iota_ints.begin(), iota_ints.end()); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; basic_adapted_random_access_iter first(iota_ints.data()); basic_adapted_random_access_iter last( iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::sort(first, last); BOOST_TEST(iota_ints == ints); } } { { random_access first(ints.data()); random_access last(ints.data() + ints.size()); const_random_access first_copy(first); const_random_access last_copy(last); std::equal(first, last, first_copy, last_copy); } { adapted_random_access_iter first(ints.data()); adapted_random_access_iter last(ints.data() + ints.size()); adapted_random_access_iter first_copy( (int const *)ints.data()); adapted_random_access_iter last_copy( (int const *)ints.data() + ints.size()); std::equal(first, last, first_copy, last_copy); } } { { random_access first(ints.data()); random_access last(ints.data() + ints.size()); const_random_access first_const(first); const_random_access last_const(last); BOOST_TEST(first == first_const); BOOST_TEST(first_const == first); BOOST_TEST(first != last_const); BOOST_TEST(last_const != first); BOOST_TEST(first <= first_const); BOOST_TEST(first_const <= first); BOOST_TEST(first >= first_const); BOOST_TEST(first_const >= first); BOOST_TEST(last_const > first); BOOST_TEST(last > first_const); BOOST_TEST(first_const < last); BOOST_TEST(first < last_const); } { adapted_random_access_iter first(ints.data()); adapted_random_access_iter last(ints.data() + ints.size()); adapted_random_access_iter first_const(first); adapted_random_access_iter last_const(last); BOOST_TEST(first == first_const); BOOST_TEST(first_const == first); BOOST_TEST(first != last_const); BOOST_TEST(last_const != first); BOOST_TEST(first <= first_const); BOOST_TEST(first_const <= first); BOOST_TEST(first >= first_const); BOOST_TEST(first_const >= first); BOOST_TEST(last_const > first); BOOST_TEST(last > first_const); BOOST_TEST(first_const < last); BOOST_TEST(first < last_const); } } { { random_access first(ints.data()); random_access last(ints.data() + ints.size()); while (first != last) first++; } { random_access first(ints.data()); random_access last(ints.data() + ints.size()); while (first != last) last--; } { basic_random_access_iter first(ints.data()); basic_random_access_iter last(ints.data() + ints.size()); while (first != last) first++; } { basic_random_access_iter first(ints.data()); basic_random_access_iter last(ints.data() + ints.size()); while (first != last) last--; } { basic_adapted_random_access_iter first(ints.data()); basic_adapted_random_access_iter last(ints.data() + ints.size()); while (first != last) first++; } { basic_adapted_random_access_iter first(ints.data()); basic_adapted_random_access_iter last(ints.data() + ints.size()); while (first != last) last--; } } { random_access first(ints.data()); random_access last(ints.data() + ints.size()); BOOST_TEST(*first == 0); BOOST_TEST(*(first + 1) == 1); BOOST_TEST(*(first + 2) == 2); BOOST_TEST(*(1 + first) == 1); BOOST_TEST(*(2 + first) == 2); BOOST_TEST(first[0] == 0); BOOST_TEST(first[1] == 1); BOOST_TEST(first[2] == 2); BOOST_TEST(*(last - 1) == 9); BOOST_TEST(*(last - 2) == 8); BOOST_TEST(*(last - 3) == 7); BOOST_TEST(last[-1] == 9); BOOST_TEST(last[-2] == 8); BOOST_TEST(last[-3] == 7); BOOST_TEST(last - first == 10); BOOST_TEST(first == first); BOOST_TEST(first != last); BOOST_TEST(first < last); BOOST_TEST(first <= last); BOOST_TEST(first <= first); BOOST_TEST(last > first); BOOST_TEST(last >= first); BOOST_TEST(last >= last); { auto first_copy = first; first_copy += 10; BOOST_TEST(first_copy == last); } { auto last_copy = last; last_copy -= 10; BOOST_TEST(last_copy == first); } } { random_access first(ints.data()); random_access last(ints.data() + ints.size()); { std::array ints_copy; std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { std::array ints_copy; std::copy( std::make_reverse_iterator(last), std::make_reverse_iterator(first), ints_copy.begin()); std::reverse(ints_copy.begin(), ints_copy.end()); BOOST_TEST(ints_copy == ints); } { std::array iota_ints; random_access first(iota_ints.data()); random_access last(iota_ints.data() + iota_ints.size()); std::iota(first, last, 0); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; random_access first(iota_ints.data()); random_access last(iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::reverse(iota_ints.begin(), iota_ints.end()); BOOST_TEST(iota_ints == ints); } { std::array iota_ints; random_access first(iota_ints.data()); random_access last(iota_ints.data() + iota_ints.size()); std::iota( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 0); std::sort(first, last); BOOST_TEST(iota_ints == ints); } } { const_random_access first(ints.data()); const_random_access last(ints.data() + ints.size()); { std::array ints_copy; std::copy(first, last, ints_copy.begin()); BOOST_TEST(ints_copy == ints); } { BOOST_TEST(std::binary_search(first, last, 3)); BOOST_TEST(std::binary_search( std::make_reverse_iterator(last), std::make_reverse_iterator(first), 3, std::greater<>{})); } } { { zip_iter first(ints.data(), ones.data()); zip_iter last(ints.data() + ints.size(), ones.data() + ones.size()); BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.end())); } { auto ints_copy = ints; std::reverse(ints_copy.begin(), ints_copy.end()); auto ones_copy = ones; zip_iter first(ints_copy.data(), ones_copy.data()); zip_iter last( ints_copy.data() + ints_copy.size(), ones_copy.data() + ones_copy.size()); BOOST_TEST(!std::equal(first, last, tuples.begin(), tuples.end())); std::sort(first, last); BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.end())); } { udt_zip_iter first(udts.data(), ones.data()); udt_zip_iter last(udts.data() + udts.size(), ones.data() + ones.size()); BOOST_TEST( std::equal(first, last, udt_tuples.begin(), udt_tuples.end())); } { auto udts_copy = udts; std::reverse(udts_copy.begin(), udts_copy.end()); auto ones_copy = ones; udt_zip_iter first(udts_copy.data(), ones_copy.data()); udt_zip_iter last( udts_copy.data() + udts_copy.size(), ones_copy.data() + ones_copy.size()); BOOST_TEST( !std::equal(first, last, udt_tuples.begin(), udt_tuples.end())); std::sort(first, last); BOOST_TEST( std::equal(first, last, udt_tuples.begin(), udt_tuples.end())); } } { basic_random_access_iter first(ints.data()); basic_random_access_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); } // Before LWG 3545 (Reimplement pointer_traits to be SFINAE-friendly), // GCC's std::to_address() breaks the contiguous_iterator concept. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416 #if !BOOST_STL_INTERFACES_USE_CONCEPTS || \ defined(__GNUC__) && __GNUC__ == 11 && __GNUC_MINOR__ >= 3 // data { BOOST_TEST(r.data() != nullptr); BOOST_TEST(r.data()[2] == 2); BOOST_TEST(empty.data() != nullptr); auto const cr = r; BOOST_TEST(cr.data() != nullptr); BOOST_TEST(cr.data()[2] == 2); auto const cempty = empty; BOOST_TEST(cempty.data() != nullptr); } #endif // size { BOOST_TEST(r.size() == 10u); BOOST_TEST(empty.size() == 0u); auto const cr = r; BOOST_TEST(cr.size() == 10u); auto const cempty = empty; BOOST_TEST(cempty.size() == 0u); } // front/back { BOOST_TEST(r.front() == 0); BOOST_TEST(r.back() == 9); auto const cr = r; BOOST_TEST(cr.front() == 0); BOOST_TEST(cr.back() == 9); } // op[] { BOOST_TEST(r[2] == 2); auto const cr = r; BOOST_TEST(cr[2] == 2); } } { zip_iter first(ints.data(), ones.data()); zip_iter last(ints.data() + ints.size(), ones.data() + ones.size()); auto r = range( first, last); auto empty = range( first, first); // range begin/end { BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.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); } // size { BOOST_TEST(r.size() == 10u); BOOST_TEST(empty.size() == 0u); auto const cr = r; BOOST_TEST(cr.size() == 10u); auto const cempty = empty; BOOST_TEST(cempty.size() == 0u); } // front/back { BOOST_TEST(r.front() == (std::tuple(0, 1))); BOOST_TEST(r.back() == (std::tuple(9, 1))); auto const cr = r; BOOST_TEST(cr.front() == (std::tuple(0, 1))); BOOST_TEST(cr.back() == (std::tuple(9, 1))); } // op[] { BOOST_TEST(r[2] == (std::tuple(2, 1))); auto const cr = r; BOOST_TEST(cr[2] == (std::tuple(2, 1))); } } return boost::report_errors(); }