// 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 // Just like std::array, except for the 0-size specialization, and the fact // that the base class makes brace-initialization wonky. template struct array : boost::stl_interfaces::sequence_container_interface< array, boost::stl_interfaces::v1::element_layout::contiguous> { using value_type = T; using pointer = T *; using const_pointer = T const *; using reference = value_type &; using const_reference = value_type const &; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using iterator = T *; using const_iterator = T const *; using reverse_iterator = boost::stl_interfaces::reverse_iterator; using const_reverse_iterator = boost::stl_interfaces::reverse_iterator; void fill(T const & x) { std::fill(begin(), end(), x); } iterator begin() noexcept { return elements_; } iterator end() noexcept { return elements_ + N; } size_type max_size() const noexcept { return N; } void swap(array & other) { using std::swap; T * element = elements_; for (auto & x : other) { swap(*element++, x); } } using base_type = boost::stl_interfaces::sequence_container_interface< array, boost::stl_interfaces::v1::element_layout::contiguous>; using base_type::begin; using base_type::end; T elements_[N]; }; using arr_type = array; void test_comparisons() { arr_type sm; sm[0] = 1; sm[1] = 2; sm[2] = 3; sm[3] = 0; sm[4] = 0; arr_type md; md[0] = 1; md[1] = 2; md[2] = 3; md[3] = 4; md[4] = 0; arr_type lg; lg[0] = 1; lg[1] = 2; lg[2] = 3; lg[3] = 4; lg[4] = 5; BOOST_TEST(sm == sm); BOOST_TEST(!(sm == md)); BOOST_TEST(!(sm == lg)); BOOST_TEST(!(sm != sm)); BOOST_TEST(sm != md); BOOST_TEST(sm != lg); BOOST_TEST(!(sm < sm)); BOOST_TEST(sm < md); BOOST_TEST(sm < lg); BOOST_TEST(sm <= sm); BOOST_TEST(sm <= md); BOOST_TEST(sm <= lg); BOOST_TEST(!(sm > sm)); BOOST_TEST(!(sm > md)); BOOST_TEST(!(sm > lg)); BOOST_TEST(sm >= sm); BOOST_TEST(!(sm >= md)); BOOST_TEST(!(sm >= lg)); BOOST_TEST(!(md == sm)); BOOST_TEST(md == md); BOOST_TEST(!(md == lg)); BOOST_TEST(!(md < sm)); BOOST_TEST(!(md < md)); BOOST_TEST(md < lg); BOOST_TEST(!(md <= sm)); BOOST_TEST(md <= md); BOOST_TEST(md <= lg); BOOST_TEST(md > sm); BOOST_TEST(!(md > md)); BOOST_TEST(!(md > lg)); BOOST_TEST(md >= sm); BOOST_TEST(md >= md); BOOST_TEST(!(md >= lg)); BOOST_TEST(!(lg == sm)); BOOST_TEST(!(lg == md)); BOOST_TEST(lg == lg); BOOST_TEST(!(lg < sm)); BOOST_TEST(!(lg < md)); BOOST_TEST(!(lg < lg)); BOOST_TEST(!(lg <= sm)); BOOST_TEST(!(lg <= md)); BOOST_TEST(lg <= lg); BOOST_TEST(lg > sm); BOOST_TEST(lg > md); BOOST_TEST(!(lg > lg)); BOOST_TEST(lg >= sm); BOOST_TEST(lg >= md); BOOST_TEST(lg >= lg); } void test_swap() { { arr_type v1; v1[0] = 3; v1[1] = 4; v1[2] = 0; v1[3] = 0; v1[4] = 0; arr_type v2; v2[0] = 4; v2[1] = 3; v2[2] = 0; v2[3] = 0; v2[4] = 0; arr_type const v1_copy = v1; arr_type const v2_copy = v2; static_assert(std::is_same::value, ""); static_assert(std::is_same::value, ""); v1.swap(v2); BOOST_TEST(v1 == v2_copy); BOOST_TEST(v2 == v1_copy); } { arr_type v1; v1[0] = 3; v1[1] = 4; v1[2] = 0; v1[3] = 0; v1[4] = 0; arr_type v2; v2[0] = 4; v2[1] = 3; v2[2] = 0; v2[3] = 0; v2[4] = 0; arr_type const v1_copy = v1; arr_type const v2_copy = v2; swap(v1, v2); BOOST_TEST(v1 == v2_copy); BOOST_TEST(v2 == v1_copy); } } template using writable_iter_t = decltype( *std::declval() = std::declval::value_type>()); static_assert( !ill_formed().begin())>:: value, ""); static_assert( !ill_formed().end())>:: value, ""); static_assert( ill_formed< writable_iter_t, decltype(std::declval().begin())>::value, ""); static_assert( ill_formed< writable_iter_t, decltype(std::declval().end())>::value, ""); static_assert( ill_formed().cbegin())>:: value, ""); static_assert( ill_formed().cend())>:: value, ""); static_assert( ill_formed< writable_iter_t, decltype(std::declval().rbegin())>::value, ""); static_assert( ill_formed< writable_iter_t, decltype(std::declval().rend())>::value, ""); static_assert( ill_formed< writable_iter_t, decltype(std::declval().crbegin())>::value, ""); static_assert( ill_formed().crend())>:: value, ""); void test_iterators() { arr_type v0; v0[0] = 3; v0[1] = 2; v0[2] = 1; v0[3] = 0; v0[4] = 0; { arr_type v = v0; static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same:: value, ""); static_assert( std::is_same:: value, ""); static_assert( std::is_same< decltype(v.crbegin()), arr_type::const_reverse_iterator>::value, ""); static_assert( std::is_same< decltype(v.crbegin()), arr_type::const_reverse_iterator>::value, ""); std::array const a = {{3, 2, 1, 0, 0}}; std::array const ra = {{0, 0, 1, 2, 3}}; BOOST_TEST(std::equal(v.begin(), v.end(), a.begin(), a.end())); BOOST_TEST(std::equal(v.cbegin(), v.cend(), a.begin(), a.end())); BOOST_TEST(std::equal(v.rbegin(), v.rend(), ra.begin(), ra.end())); BOOST_TEST(std::equal(v.crbegin(), v.crend(), ra.begin(), ra.end())); arr_type v2; v2[0] = 8; v2[1] = 2; v2[2] = 1; v2[3] = 0; v2[4] = 9; *v.begin() = 8; *v.rbegin() = 9; BOOST_TEST(v == v2); } { arr_type const v = v0; static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same::value, ""); static_assert( std::is_same< decltype(v.rbegin()), arr_type::const_reverse_iterator>::value, ""); static_assert( std::is_same< decltype(v.rbegin()), arr_type::const_reverse_iterator>::value, ""); static_assert( std::is_same< decltype(v.crbegin()), arr_type::const_reverse_iterator>::value, ""); static_assert( std::is_same< decltype(v.crbegin()), arr_type::const_reverse_iterator>::value, ""); std::array const a = {{3, 2, 1, 0, 0}}; std::array const ra = {{0, 0, 1, 2, 3}}; BOOST_TEST(std::equal(v.begin(), v.end(), a.begin(), a.end())); BOOST_TEST(std::equal(v.cbegin(), v.cend(), a.begin(), a.end())); BOOST_TEST(std::equal(v.rbegin(), v.rend(), ra.begin(), ra.end())); BOOST_TEST(std::equal(v.crbegin(), v.crend(), ra.begin(), ra.end())); } } template< typename Container, typename ValueType = typename Container::value_type> using lvalue_push_front_t = decltype( std::declval().push_front(std::declval())); template< typename Container, typename ValueType = typename Container::value_type> using rvalue_push_front_t = decltype(std::declval().push_front(0)); template using pop_front_t = decltype(std::declval().pop_front()); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); using std_deq_int = std::deque; static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); template< typename Container, typename ValueType = typename Container::value_type> using lvalue_push_back_t = decltype( std::declval().push_back(std::declval())); template< typename Container, typename ValueType = typename Container::value_type> using rvalue_push_back_t = decltype(std::declval().push_back(0)); template using pop_back_t = decltype(std::declval().pop_back()); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); using std_vec_int = std::vector; static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); void test_front_back() { { arr_type v; v[0] = 0; v[1] = 0; v[2] = 0; v[3] = 0; v[4] = 0; static_assert(std::is_same::value, ""); static_assert(std::is_same::value, ""); v.front() = 9; v.back() = 8; BOOST_TEST(v[0] == v.front()); BOOST_TEST(v[4] == v.back()); } { arr_type v0; v0[0] = 3; v0[1] = 0; v0[2] = 2; v0[3] = 0; v0[4] = 1; arr_type const v = v0; BOOST_TEST(v.front() == 3); BOOST_TEST(v.back() == 1); static_assert( std::is_same::value, ""); static_assert(std::is_same::value, ""); } } void test_cindex_at() { arr_type v0; v0[0] = 3; v0[1] = 2; v0[2] = 1; v0[3] = 0; v0[4] = 0; { arr_type v = v0; BOOST_TEST(v[0] == 3); BOOST_TEST(v[1] == 2); BOOST_TEST(v[2] == 1); BOOST_TEST_NO_THROW(v.at(0)); BOOST_TEST_NO_THROW(v.at(1)); BOOST_TEST_NO_THROW(v.at(2)); BOOST_TEST_THROWS(v.at(5), std::out_of_range); static_assert(std::is_same::value, ""); static_assert(std::is_same::value, ""); v[0] = 8; v.at(1) = 9; BOOST_TEST(v[0] == 8); BOOST_TEST(v[1] == 9); } { arr_type const v = v0; BOOST_TEST(v[0] == 3); BOOST_TEST(v[1] == 2); BOOST_TEST(v[2] == 1); BOOST_TEST_NO_THROW(v.at(0)); BOOST_TEST_NO_THROW(v.at(1)); BOOST_TEST_NO_THROW(v.at(2)); BOOST_TEST_THROWS(v.at(5), std::out_of_range); static_assert(std::is_same::value, ""); static_assert(std::is_same::value, ""); } } template using resize_t = decltype(std::declval().resize(0)); static_assert(ill_formed::value, ""); static_assert(!ill_formed::value, ""); template< typename Container, typename ValueType = typename Container::value_type> using lvalue_insert_t = decltype(std::declval().insert( std::declval().begin(), std::declval())); template< typename Container, typename ValueType = typename Container::value_type> using rvalue_insert_t = decltype(std::declval().insert( std::declval().begin(), std::declval())); template< typename Container, typename ValueType = typename Container::value_type> using insert_n_t = decltype(std::declval().insert( std::declval().begin(), 2, std::declval())); template< typename Container, typename ValueType = typename Container::value_type> using insert_il_t = decltype(std::declval().insert( std::declval().begin(), std::initializer_list{})); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); // TODO: Broken in v1. Adding the proper constraint ICE's GCC 8, or // infinitely recurses within the compiler for GCC and Clang, depending on the // constraint technique used. #if 0 static_assert(ill_formed::value, ""); #endif static_assert(ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); template using erase_t = decltype( std::declval().erase(std::declval().begin())); static_assert(ill_formed::value, ""); static_assert(!ill_formed::value, ""); template using assign_t = decltype(std::declval().assign( std::declval(), std::declval())); template using assign_n_t = decltype(std::declval().assign(5, 5)); template using assign_il_t = decltype(std::declval().assign(std::initializer_list{})); template using assignment_operator_il_t = decltype(std::declval() = std::initializer_list{}); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); static_assert(ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); static_assert(!ill_formed::value, ""); template using clear_t = decltype(std::declval().clear()); static_assert(ill_formed::value, ""); static_assert(!ill_formed::value, ""); int main() { test_comparisons(); test_swap(); test_iterators(); test_front_back(); test_cindex_at(); return boost::report_errors(); }