Index: libcxx/include/__ranges/empty.h =================================================================== --- libcxx/include/__ranges/empty.h +++ libcxx/include/__ranges/empty.h @@ -13,7 +13,6 @@ #include <__iterator/concepts.h> #include <__ranges/access.h> #include <__ranges/size.h> -#include <__utility/forward.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -29,13 +28,13 @@ namespace __empty { template concept __member_empty = requires(_Tp&& __t) { - bool(_VSTD::forward<_Tp>(__t).empty()); + bool(__t.empty()); }; template concept __can_invoke_size = !__member_empty<_Tp> && - requires(_Tp&& __t) { ranges::size(_VSTD::forward<_Tp>(__t)); }; + requires(_Tp&& __t) { ranges::size(__t); }; template concept __can_compare_begin_end = @@ -50,13 +49,13 @@ template <__member_empty _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const noexcept(noexcept(bool(__t.empty()))) { - return __t.empty(); + return bool(__t.empty()); } template <__can_invoke_size _Tp> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const - noexcept(noexcept(ranges::size(_VSTD::forward<_Tp>(__t)))) { - return ranges::size(_VSTD::forward<_Tp>(__t)) == 0; + noexcept(noexcept(ranges::size(__t))) { + return ranges::size(__t) == 0; } template<__can_compare_begin_end _Tp> Index: libcxx/test/std/ranges/range.access/empty.pass.cpp =================================================================== --- libcxx/test/std/ranges/range.access/empty.pass.cpp +++ libcxx/test/std/ranges/range.access/empty.pass.cpp @@ -15,11 +15,11 @@ #include #include +#include #include "test_macros.h" #include "test_iterators.h" using RangeEmptyT = decltype(std::ranges::empty); -using RangeSizeT = decltype(std::ranges::size); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); @@ -41,12 +41,16 @@ static_assert(!std::ranges::empty(std::as_const(array_of_incomplete))); static_assert(!std::ranges::empty(static_cast(array_of_incomplete))); -struct NonConstSizeAndEmpty { - int size(); +struct InputRangeWithoutSize { + cpp17_input_iterator begin() const; + cpp17_input_iterator end() const; +}; +static_assert(!std::is_invocable_v); + +struct NonConstEmpty { bool empty(); }; -static_assert(!std::is_invocable_v); -static_assert(!std::is_invocable_v); +static_assert(!std::is_invocable_v); struct HasMemberAndFunction { constexpr bool empty() const { return true; } @@ -60,7 +64,7 @@ static_assert(!std::is_invocable_v); struct BoolConvertible { - constexpr /*TODO: explicit*/ operator bool() noexcept(false) { return true; } + constexpr explicit operator bool() noexcept(false) { return true; } }; struct BoolConvertibleReturnType { constexpr BoolConvertible empty() noexcept { return {}; } @@ -159,9 +163,7 @@ assert(std::ranges::empty(e) == false); // e.empty() assert(std::ranges::empty(std::as_const(e)) == true); // e.begin() == e.end() -#if 0 // TODO FIXME assert(std::ranges::empty(EvilBeginEnd())); -#endif return true; }