This repository was archived by the owner on Jul 9, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathFunctionTypeTraits.h
More file actions
136 lines (117 loc) · 4.1 KB
/
Copy pathFunctionTypeTraits.h
File metadata and controls
136 lines (117 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Helpers to manipulate function types that don't fit in TypeTraits.h */
#ifndef mozilla_FunctionTypeTraits_h
#define mozilla_FunctionTypeTraits_h
#include <tuple>
namespace mozilla {
// Main FunctionTypeTraits declaration, taking one template argument.
//
// Given a function type, FunctionTypeTraits will expose the following members:
// - ReturnType: Return type.
// - arity: Number of parameters (size_t).
// - ParameterType<N>: Type of the Nth** parameter, 0-indexed.
//
// ** `ParameterType<N>` with `N` >= `arity` is allowed and gives `void`.
// This prevents compilation errors when trying to access a type outside of the
// function's parameters, which is useful for parameters checks, e.g.:
// template<typename F>
// auto foo(F&&)
// -> enable_if(FunctionTypeTraits<F>::arity == 1 &&
// is_same<FunctionTypeTraits<F>::template ParameterType<0>,
// int>::value,
// void)
// {
// // This function will only be enabled if `F` takes one `int`.
// // Without the permissive ParameterType<any N>, it wouldn't even compile.
//
// Note: FunctionTypeTraits does not work with generic lambdas `[](auto&) {}`,
// because parameter types cannot be known until an actual invocation when types
// are inferred from the given arguments.
template<typename T>
struct FunctionTypeTraits;
// Remove reference and pointer wrappers, if any.
template<typename T>
struct FunctionTypeTraits<T&> : public FunctionTypeTraits<T>
{
};
template<typename T>
struct FunctionTypeTraits<T&&> : public FunctionTypeTraits<T>
{
};
template<typename T>
struct FunctionTypeTraits<T*> : public FunctionTypeTraits<T>
{
};
// Extract `operator()` function from callables (e.g. lambdas, std::function).
template<typename T>
struct FunctionTypeTraits : public FunctionTypeTraits<decltype(&T::operator())>
{
};
namespace detail {
// If `safe`, retrieve the `N`th type from `As`, otherwise `void`.
// See top description for reason.
template<bool safe, size_t N, typename... As>
struct TupleElementSafe;
template<size_t N, typename... As>
struct TupleElementSafe<true, N, As...>
{
using Type = typename std::tuple_element<N, std::tuple<As...>>::type;
};
template<size_t N, typename... As>
struct TupleElementSafe<false, N, As...>
{
using Type = void;
};
template<typename R, typename... As>
struct FunctionTypeTraitsHelper
{
using ReturnType = R;
static constexpr size_t arity = sizeof...(As);
template<size_t N>
using ParameterType =
typename TupleElementSafe<(N < sizeof...(As)), N, As...>::Type;
};
} // namespace detail
// Specialization for free functions.
template<typename R, typename... As>
struct FunctionTypeTraits<R(As...)> : detail::FunctionTypeTraitsHelper<R, As...>
{
};
// Specialization for non-const member functions.
template<typename C, typename R, typename... As>
struct FunctionTypeTraits<R (C::*)(As...)>
: detail::FunctionTypeTraitsHelper<R, As...>
{
};
// Specialization for const member functions.
template<typename C, typename R, typename... As>
struct FunctionTypeTraits<R (C::*)(As...) const>
: detail::FunctionTypeTraitsHelper<R, As...>
{
};
#ifdef NS_HAVE_STDCALL
// Specialization for __stdcall free functions.
template<typename R, typename... As>
struct FunctionTypeTraits<R NS_STDCALL(As...)>
: detail::FunctionTypeTraitsHelper<R, As...>
{
};
// Specialization for __stdcall non-const member functions.
template<typename C, typename R, typename... As>
struct FunctionTypeTraits<R (NS_STDCALL C::*)(As...)>
: detail::FunctionTypeTraitsHelper<R, As...>
{
};
// Specialization for __stdcall const member functions.
template<typename C, typename R, typename... As>
struct FunctionTypeTraits<R (NS_STDCALL C::*)(As...) const>
: detail::FunctionTypeTraitsHelper<R, As...>
{
};
#endif // NS_HAVE_STDCALL
} // namespace mozilla
#endif // mozilla_FunctionTypeTraits_h