// { dg-do run { target c++23 } } #include #include #include #include #include template constexpr void do_test() { // The vector's value_type. using V = typename std::allocator_traits::value_type; // The range's value_type. using T = std::ranges::range_value_t; T a[]{1,2,3,4,5,6,7,8,9}; auto eq = [](const std::vector& l, std::span r) { if (l.size() != r.size()) return false; for (auto i = 0u; i < l.size(); ++i) if (l[i] != r[i]) return false; return true; }; std::vector v; v.insert_range(v.begin(), Range(a, a)); VERIFY( v.empty() ); VERIFY( v.capacity() == 0 ); v.insert_range(v.begin(), Range(a, a+4)); VERIFY( eq(v, {a, a+4}) ); v.clear(); v.insert_range(v.begin(), Range(a+4, a+9)); VERIFY( eq(v, {a+4, a+9}) ); v.insert_range(v.begin(), Range(a, a+4)); VERIFY( eq(v, a) ); v.clear(); v.shrink_to_fit(); auto it = v.insert_range(v.begin(), Range(a, a+3)); VERIFY( it == v.begin() ); it = v.insert_range(v.end(), Range(a+6, a+9)); VERIFY( it == v.begin()+3 ); it = v.insert_range(v.begin()+3, Range(a+3, a+6)); VERIFY( it == v.begin()+3 ); VERIFY( eq(v, a) ); v.resize(3); it = v.insert_range(v.begin()+1, Range(a+4, a+9)); VERIFY( it == v.begin()+1 ); it = v.insert_range(v.begin()+1, Range(a+1, a+4)); VERIFY( it == v.begin()+1 ); v.resize(9); VERIFY( eq(v, a) ); it = v.insert_range(v.begin() + 6, Range(a, a)); VERIFY( it == v.begin() + 6 ); VERIFY( eq(v, a) ); } template constexpr void do_test_a() { do_test>(); do_test>(); } constexpr bool test_ranges() { using namespace __gnu_test; do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); do_test_a>(); // Not lvalue-convertible to int struct C { constexpr C(int v) : val(v) { } constexpr operator int() && { return val; } constexpr bool operator==(int b) const { return b == val; } int val; }; using rvalue_input_range = test_range; do_test>(); return true; } struct SelfAssignChecker { static int moveCounter; static int copyCounter; SelfAssignChecker() = default; constexpr SelfAssignChecker(int v) : val(v) { } SelfAssignChecker(const SelfAssignChecker&) = default; SelfAssignChecker(SelfAssignChecker&&) = default; SelfAssignChecker operator=(const SelfAssignChecker& rhs) { if (this == &rhs) ++copyCounter; this->val = rhs.val; return *this; } SelfAssignChecker operator=(SelfAssignChecker&& rhs) { if (this == &rhs) ++moveCounter; this->val = rhs.val; return *this; } int val; friend bool operator==(SelfAssignChecker, SelfAssignChecker) = default; }; int SelfAssignChecker::moveCounter = 0; int SelfAssignChecker::copyCounter = 0; void test_pr121313() { using namespace __gnu_test; SelfAssignChecker::copyCounter = SelfAssignChecker::moveCounter = 0; do_test, std::allocator>(); VERIFY( SelfAssignChecker::moveCounter == 0 ); VERIFY( SelfAssignChecker::copyCounter == 0 ); SelfAssignChecker::copyCounter = SelfAssignChecker::moveCounter = 0; do_test, std::allocator>(); VERIFY( SelfAssignChecker::moveCounter == 0 ); VERIFY( SelfAssignChecker::copyCounter == 0 ); } int main() { test_ranges(); test_pr121313(); static_assert( test_ranges() ); }