Skip to content

[libc++] static_cast in ranges::__crend::__fn is not required #64250

@Fznamznon

Description

@Fznamznon

I discovered this while working on D152003 which is a fix for #62863 . Per C++20 static cast to array of unknown bound U[] should yield the type U[1].
Now D152003 breaks libc++ tests, since the following static assertion fails with it:

#include <ranges>

using RangeCREndT = decltype(std::ranges::crend);
static_assert(!std::is_invocable_v<RangeCREndT, int (&)[]>);

source/llvm-project/build/bin/clang++ -std=c++20 t.cpp -stdlib=libc++ -c
t.cpp:4:15: error: static assertion failed due to requirement '!std::is_invocable_v<const std::ranges::__crend::__fn, int (&)[]>'
    4 | static_assert(!std::is_invocable_v<RangeCREndT, int (&)[]>);
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

I noticed that that in libc++ there is a bunch of explicit static casts in ranges::__crend::__fn that endup transformed:

namespace ranges {
namespace __crend {                                                                    
struct __fn {
  template <class _Tp>
    requires is_lvalue_reference_v<_Tp&&>                                              
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  constexpr auto operator()(_Tp&& __t) const
    noexcept(noexcept(ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t))))
    -> decltype(      ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)))  
    { return          ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)); }
                                                                                       
  template <class _Tp>                                                                 
    requires is_rvalue_reference_v<_Tp&&>                                              
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
  constexpr auto operator()(_Tp&& __t) const
    noexcept(noexcept(ranges::rend(static_cast<const _Tp&&>(__t))))                    
    -> decltype(      ranges::rend(static_cast<const _Tp&&>(__t)))
    { return          ranges::rend(static_cast<const _Tp&&>(__t)); }
};
} // namespace __crend

Per discussion in D152003 we agreed that it is a bug in libc++ so I'm filing this issue so it won't be lost/forgotten.

cc @mordante @philnik777

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.rangesIssues related to `<ranges>`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions