blob: b5bb8b430a814ecb6788ba3660f92d92dc934fc2 [file] [log] [blame]
Austin Schuhb4691e92020-12-31 12:37:18 -08001// Copyright 2019 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
16#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
17
18#include <cassert>
19#include <functional>
20#include <type_traits>
21
22#include "absl/base/internal/invoke.h"
23#include "absl/meta/type_traits.h"
24
25namespace absl {
26ABSL_NAMESPACE_BEGIN
27namespace functional_internal {
28
29// Like a void* that can handle function pointers as well. The standard does not
30// allow function pointers to round-trip through void*, but void(*)() is fine.
31//
32// Note: It's important that this class remains trivial and is the same size as
33// a pointer, since this allows the compiler to perform tail-call optimizations
34// when the underlying function is a callable object with a matching signature.
35union VoidPtr {
36 const void* obj;
37 void (*fun)();
38};
39
40// Chooses the best type for passing T as an argument.
41// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are
42// passed by value.
43template <typename T>
44constexpr bool PassByValue() {
45 return !std::is_lvalue_reference<T>::value &&
46 absl::is_trivially_copy_constructible<T>::value &&
47 absl::is_trivially_copy_assignable<
48 typename std::remove_cv<T>::type>::value &&
49 std::is_trivially_destructible<T>::value &&
50 sizeof(T) <= 2 * sizeof(void*);
51}
52
53template <typename T>
54struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {};
55
56// An Invoker takes a pointer to the type-erased invokable object, followed by
57// the arguments that the invokable object expects.
58//
59// Note: The order of arguments here is an optimization, since member functions
60// have an implicit "this" pointer as their first argument, putting VoidPtr
61// first allows the compiler to perform tail-call optimization in many cases.
62template <typename R, typename... Args>
63using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);
64
65//
66// InvokeObject and InvokeFunction provide static "Invoke" functions that can be
67// used as Invokers for objects or functions respectively.
68//
69// static_cast<R> handles the case the return type is void.
70template <typename Obj, typename R, typename... Args>
71R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
72 auto o = static_cast<const Obj*>(ptr.obj);
73 return static_cast<R>(
74 absl::base_internal::invoke(*o, std::forward<Args>(args)...));
75}
76
77template <typename Fun, typename R, typename... Args>
78R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
79 auto f = reinterpret_cast<Fun>(ptr.fun);
80 return static_cast<R>(
81 absl::base_internal::invoke(f, std::forward<Args>(args)...));
82}
83
84template <typename Sig>
85void AssertNonNull(const std::function<Sig>& f) {
86 assert(f != nullptr);
87 (void)f;
88}
89
90template <typename F>
91void AssertNonNull(const F&) {}
92
93template <typename F, typename C>
94void AssertNonNull(F C::*f) {
95 assert(f != nullptr);
96 (void)f;
97}
98
99template <bool C>
100using EnableIf = typename ::std::enable_if<C, int>::type;
101
102} // namespace functional_internal
103ABSL_NAMESPACE_END
104} // namespace absl
105
106#endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_