[libcxx-commits] [libcxx] [libc++] Implement `std::function_ref` (PR #186692)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 19 11:18:44 PDT 2026


================
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// template<auto c, class F>
+//   constexpr function_ref(constant_wrapper<c, F>) noexcept;
+// template<auto c, class F, class U>
+//   constexpr function_ref(constant_wrapper<c, F>, U&& obj) noexcept;
+// template<auto c, class F, class T>
+//   constexpr function_ref(constant_wrapper<c, F>, cv T* obj) noexcept;
+
+// Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
+
+// For the first overload, f ArgTypes is not an empty pack and all types in remove_cvref_t<ArgTypes>...
+// satisfy constexpr-param then constant_wrapper<INVOKE (f.value, remove_cvref_t<ArgTypes>::value...)>
+// is not a valid type.
+
+#include <functional>
+#include <utility>
+
+struct A {
+  void f();
+};
+
+struct B {
+  constexpr int operator()(std::constant_wrapper<42>) const { return 42; }
+  constexpr int operator()(int) const { return 42; }
+};
+
+// clang-format off
+void test() {
+  std::function_ref<void()> f1(std::cw<static_cast<void (*)()>(nullptr)>); // expected-note-re{{in instantiation of function template specialization 'std::function_ref{{.*}}' requested here}}
+  // expected-error@*:* {{static assertion failed due to requirement '__f.value != nullptr': the function pointer should not be a nullptr}}
+
+  std::function_ref<void(A)> f2(std::cw<static_cast<void (A::*)()>(nullptr)>); // expected-note-re{{in instantiation of function template specialization 'std::function_ref{{.*}}' requested here}}
+  // expected-error@*:* {{static assertion failed due to requirement '__f.value != nullptr': the function pointer should not be a nullptr}}
+
+  std::function_ref<void(std::constant_wrapper<42>)> f33(std::cw<B{}>);
+  // expected-error@*:* {{static assertion failed due to requirement '!requires { std::constant_wrapper<std::__cw_fixed_value<int>{42}, int>; }': cw(args...) should be equivalent to fn(args...), otherwise the intended behavior for a function_ref constructed from cw would be ambiguous}}
----------------
ldionne wrote:

I would suggest that we hardcode a bit less of these assertions in the test, to make them more robust to diagnostic changes. For example we could only match the static assertion message, which we control entirely. I think we could also drop the `expected-note`s, which I would guess are likely to change?

To allow dropping notes, look for a flag we're passing in other verity test (like `-verify-ignore-unexpected=notes` or something).

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


More information about the libcxx-commits mailing list