// Copyright (C) 2019-2022 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License along // with this library; see the file COPYING3. If not see // . // { dg-options "-std=gnu++2a" } // { dg-do run { target c++2a } } #include #include #include static_assert(__gnu_test::is_customization_point_object(std::ranges::empty)); using std::same_as; void test01() { struct R { constexpr int empty() const & { return 0; } constexpr const void* empty() const && { return this; } }; constexpr R r; static_assert( !std::ranges::empty(r) ); static_assert( same_as ); // PR libstdc++/100824 // ranges::empty should treat the subexpression as an lvalue static_assert( !std::ranges::empty(std::move(r)) ); static_assert( same_as ); } void test02() { using __gnu_test::test_range; using __gnu_test::test_sized_range; using __gnu_test::random_access_iterator_wrapper; using __gnu_test::forward_iterator_wrapper; using __gnu_test::input_iterator_wrapper; using __gnu_test::output_iterator_wrapper; int a[] = { 0, 1 }; VERIFY( !std::ranges::empty(a) ); test_range r(a); VERIFY( !std::ranges::empty(r) ); test_range i(a); VERIFY( !std::ranges::empty(i) ); test_sized_range sr(a); VERIFY( !std::ranges::empty(sr) ); test_sized_range si(a); VERIFY( !std::ranges::empty(si) ); test_sized_range so(a); VERIFY( !std::ranges::empty(so) ); } void test03() { // PR libstdc++/100824 // ranges::empty should treat the subexpression as an lvalue struct R { constexpr bool empty() & { return true; } }; static_assert( std::ranges::empty(R{}) ); struct R2 { constexpr unsigned size() & { return 0; } }; static_assert( std::ranges::empty(R2{}) ); } void test04() { struct E1 { bool empty() const noexcept { return {}; } }; static_assert( noexcept(std::ranges::empty(E1{})) ); struct E2 { bool empty() const noexcept(false) { return {}; } }; static_assert( ! noexcept(std::ranges::empty(E2{})) ); struct E3 { struct B { explicit operator bool() const noexcept(false) { return true; } }; B empty() const noexcept { return {}; } }; static_assert( ! noexcept(std::ranges::empty(E3{})) ); } template concept has_empty = requires (T& t) { std::ranges::empty(t); }; // If T is an array of unknown bound, ranges::empty(E) is ill-formed. static_assert( ! has_empty ); static_assert( ! has_empty ); static_assert( ! has_empty ); struct Incomplete; static_assert( ! has_empty ); int main() { test01(); test02(); test03(); test04(); }