libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
function_traits.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2018 Kitsune Ral <kitsune-ral@users.sf.net>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <type_traits>
7#include <tuple>
8
9namespace Quotient {
10
11namespace _impl {
12 template <typename>
13 struct fn_traits {};
14}
15
16/// Determine traits of an arbitrary function/lambda/functor
17/*!
18 * Doesn't work with generic lambdas and function objects that have
19 * operator() overloaded.
20 * \sa
21 * https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda#7943765
22 */
23template <typename T>
25 : public _impl::fn_traits<std::remove_reference_t<T>> {};
26
27// Specialisation for a function
28template <typename ReturnT, typename... ArgTs>
29struct function_traits<ReturnT(ArgTs...)> {
30 using return_type = ReturnT;
31 using arg_types = std::tuple<ArgTs...>;
32};
33
34namespace _impl {
35 template <typename>
36 struct fn_object_traits;
37
38 // Specialisation for a lambda function
39 template <typename ReturnT, typename ClassT, typename... ArgTs>
40 struct fn_object_traits<ReturnT (ClassT::*)(ArgTs...)>
41 : function_traits<ReturnT(ArgTs...)> {};
42
43 // Specialisation for a const lambda function
44 template <typename ReturnT, typename ClassT, typename... ArgTs>
45 struct fn_object_traits<ReturnT (ClassT::*)(ArgTs...) const>
46 : function_traits<ReturnT(ArgTs...)> {};
47
48 // Specialisation for function objects with (non-overloaded) operator()
49 // (this includes non-generic lambdas)
50 template <typename T>
51 requires requires { &T::operator(); }
52 struct fn_traits<T>
53 : public fn_object_traits<decltype(&T::operator())> {};
54
55 // Specialisation for a member function in a non-functor class
56 template <typename ReturnT, typename ClassT, typename... ArgTs>
57 struct fn_traits<ReturnT (ClassT::*)(ArgTs...)>
58 : function_traits<ReturnT(ClassT, ArgTs...)> {};
59
60 // Specialisation for a const member function
61 template <typename ReturnT, typename ClassT, typename... ArgTs>
62 struct fn_traits<ReturnT (ClassT::*)(ArgTs...) const>
63 : function_traits<ReturnT(const ClassT&, ArgTs...)> {};
64
65 // Specialisation for a constref member function
66 template <typename ReturnT, typename ClassT, typename... ArgTs>
67 struct fn_traits<ReturnT (ClassT::*)(ArgTs...) const&>
68 : function_traits<ReturnT(const ClassT&, ArgTs...)> {};
69
70 // Specialisation for a prvalue member function
71 template <typename ReturnT, typename ClassT, typename... ArgTs>
72 struct fn_traits<ReturnT (ClassT::*)(ArgTs...) &&>
73 : function_traits<ReturnT(ClassT&&, ArgTs...)> {};
74
75 // Specialisation for a pointer-to-member
76 template <typename ReturnT, typename ClassT>
77 struct fn_traits<ReturnT ClassT::*>
78 : function_traits<ReturnT&(ClassT)> {};
79
80 // Specialisation for a const pointer-to-member
81 template <typename ReturnT, typename ClassT>
82 struct fn_traits<const ReturnT ClassT::*>
83 : function_traits<const ReturnT&(ClassT)> {};
84} // namespace _impl
85
86template <typename FnT, int ArgN = 0>
87using fn_arg_t =
88 std::tuple_element_t<ArgN, typename function_traits<FnT>::arg_types>;
89
90template <typename FnT>
91constexpr auto fn_arg_count_v =
93
94} // namespace Quotient
constexpr auto fn_arg_count_v
Determine traits of an arbitrary function/lambda/functor.