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