[libcxx-commits] [libcxx] [libc++] Fix ill-formed return in function_ref's static-call path (PR #228868)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Oct 4 06:21:23 PDT 2026


================
@@ -106,7 +106,10 @@ class function_ref<_Rp(_ArgTypes...) _LIBCPP_FUNCTION_REF_CV noexcept(__is_noexc
     using _Dn = remove_cv_t<_Tp>;
     if constexpr (__statically_callable<_Dn, __arg_t<_ArgTypes>...>) {
       __call_ = [](__storage_t, __arg_t<_ArgTypes>... __args) static noexcept(__is_noexcept) -> _Rp {
-        return _Dn::operator()(std::forward<__arg_t<_ArgTypes>>(__args)...);
+        if constexpr (is_void_v<_Rp>)
+          _Dn::operator()(std::forward<__arg_t<_ArgTypes>>(__args)...);
+        else
+          return _Dn::operator()(std::forward<__arg_t<_ArgTypes>>(__args)...);
----------------
Kim-J-Smith wrote:

@huixie90 `static_cast` effects the overload resolution.

```cpp
#include <functional>
#include <cassert>

struct R {
    int which;
    R(long) : which(0) {} // implicit path
    explicit R(int) : which(1) {} // explicit path
};
struct Call { static int operator()() { return {}; } };

int main() {
    auto r1 = std::invoke_r<R>(Call{}); // 0
    auto r2 = static_cast<R>(Call{}()); // 1
    assert(r1.which == r2.which); // fail
}
```

So the `if constexpr (is_void_v<_Rp>)` branch is still needed.

https://github.com/llvm/llvm-project/pull/228868


More information about the libcxx-commits mailing list