[libcxx-commits] [libcxx] [libc++] Implement `std::function_ref` (PR #186692)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jun 5 01:01:35 PDT 2026
================
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FUNCTIONAL_FUNCTION_REF_COMMON_H
+#define _LIBCPP___FUNCTIONAL_FUNCTION_REF_COMMON_H
+
+#include <__config>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_const.h>
+#include <__type_traits/is_function.h>
+#include <__type_traits/is_object.h>
+#include <__type_traits/is_reference.h>
+#include <__type_traits/is_trivially_copyable.h>
+#include <__type_traits/remove_cv.h>
+#include <__type_traits/remove_pointer.h>
+#include <__utility/constant_wrapper.h>
+#include <__utility/declval.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <class...>
+class function_ref;
+
+template <class _Fn1, class _Fn2>
+struct __is_convertible_from_specialization : false_type {};
+
+union __function_ref_storage {
+ void* __obj_ptr_;
+ void (*__fn_ptr_)();
+
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __function_ref_storage() noexcept : __obj_ptr_(nullptr) {}
+
+ template <class _Tp>
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit __function_ref_storage(_Tp* __ptr) noexcept {
+ if constexpr (is_object_v<_Tp>) {
+ __obj_ptr_ = const_cast<remove_cv_t<_Tp>*>(__ptr);
+ } else {
+ static_assert(is_function_v<_Tp>);
+ __fn_ptr_ = reinterpret_cast<void (*)()>(__ptr);
+ }
+ }
+
+ template <class _Tp>
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __get(__function_ref_storage __storage) {
+ if constexpr (is_object_v<_Tp>) {
+ return static_cast<_Tp*>(__storage.__obj_ptr_);
+ } else {
+ static_assert(is_function_v<_Tp>);
+ return reinterpret_cast<_Tp*>(__storage.__fn_ptr_);
+ }
+ }
+};
+
+template <class _Fp, class _Tp>
+struct __function_ref_bind {};
+
+// F is of the form R(*)(G, A...) noexcept(E) for a type G.
+template <bool _Noexcept, class _Tp, class _Rp, class _Gp, class... _ArgTypes>
+struct __function_ref_bind<_Rp (*)(_Gp, _ArgTypes...) noexcept(_Noexcept), _Tp> {
+ using type _LIBCPP_NODEBUG = _Rp(_ArgTypes...) noexcept(_Noexcept);
+};
+
+template <class _Tp, class _Mp, class _Gp>
+ requires is_object_v<_Mp>
+struct __function_ref_bind<_Mp _Gp::*, _Tp> {
+ using type _LIBCPP_NODEBUG = invoke_result_t<_Mp _Gp::*, _Tp&>() noexcept;
+};
+
+template <class _Fp, class _Tp>
+using __function_ref_bind_t _LIBCPP_NODEBUG = __function_ref_bind<_Fp, _Tp>::type;
+
+template <class _Fp>
+ requires is_function_v<_Fp>
+function_ref(_Fp*) -> function_ref<_Fp>;
+
+template <auto _Cw, class _Fn>
+ requires is_function_v<remove_pointer_t<_Fn>>
+function_ref(constant_wrapper<_Cw, _Fn>) -> function_ref<remove_pointer_t<_Fn>>;
+
+template <auto _Cw, class _Fn, class _Tp>
+function_ref(constant_wrapper<_Cw, _Fn>, _Tp&&) -> function_ref<__function_ref_bind_t<_Fn, _Tp&>>;
+
+template <class>
+constexpr bool __is_constant_wrapper = false;
+
+template <auto _Value>
+constexpr bool __is_constant_wrapper<constant_wrapper<_Value>> = true;
+
+template <class _Arg>
+struct __function_ref_arg_fwd {
+ using type _LIBCPP_NODEBUG = _Arg&&;
+};
+
+template <class _Arg>
+ requires(!is_reference_v<_Arg> && is_trivially_copyable_v<_Arg> && sizeof(_Arg) <= 16)
----------------
philnik777 wrote:
> The majority of users of libc++ i believe do not use Itanium ABI.
Where did you get that from? The Itanium ABI is basically the only ABI we make guarantees about (with some vendor modifications in some cases).
https://github.com/llvm/llvm-project/pull/186692
More information about the libcxx-commits
mailing list