Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
function-signature-test.cpp
Go to the documentation of this file.
1/*
2 FunctionSignature(Test) - metaprogramming to extract function signature type
3
4 Copyright (C)
5 2017, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
19#include "lib/test/run.hpp"
20#include "lib/format-cout.hpp"
21#include "lib/format-util.hpp"
22#include "lib/meta/function.hpp"
23
24#include <functional>
25#include <string>
26
27
28using std::function;
29using std::placeholders::_1;
30using std::bind;
31using std::string;
32using std::tuple;
33using std::move;
34
35
36namespace lib {
37namespace meta {
38namespace test {
39
40 using lib::meta::_Fun;
42
43
44 namespace { // test subjects
45
46 int
48 {
49 return -i+1;
50 }
51
52 struct Functor
53 {
54 int ii = 2;
55
56 int
58 {
59 return ii + freeFun(i2);
60 }
61
62 int
64 {
65 return 2*ii - fun(i2);
66 }
67
68 static int
70 {
71 return 2*freeFun (i);
72 }
73 };
74
75
76 /* ===== diagnostics helper ===== */
77
78 template<typename F>
79 string
81 {
83 }
84
85 template<typename F>
86 string
88 {
90 }
91
92 template<typename F>
93 string
95 {
97 }
98
99 template<typename F>
100 string
102 {
104 }
105
106 } // (End) test subjects
107
108
109 using Func = function<int(uint)>;
110 using FuncF = function<int(Functor&, uint)>;
111
112
113
114
115
116
117 /*********************************************************************/
128 class FunctionSignature_test : public Test
129 {
130 virtual void
131 run (Arg)
132 {
133 // this is how the key trick of the _Fun traits template works:
134 // for anything "function like" we retrieve a member-pointer to the function call operator
135 // which we then pass on to the dedicated overload for member pointers
136 CHECK ("int (Functor::*)(uint)" == typeStr<decltype(&Functor::operator())>());
137
138
139 Func f1{freeFun};
140 Func f2{&freeFun};
141
142 Func f3{Functor::staticFun};
143 Func f4{&Functor::staticFun};
144
145
146 Functor funk;
147
148
149 auto lambda = [&](uint ii) { return funk.fun(ii); };
150
151 Func f5{lambda};
152
153 CHECK ("int (uint)" == showSig (freeFun));
154 CHECK ("int (uint)" == showSig (&freeFun));
155 CHECK ("int (uint)" == showSig (Functor::staticFun));
156 CHECK ("int (uint)" == showSig (lambda));
157 CHECK ("int (uint)" == showSig (f5));
158
159
160 CHECK ("int (uint)" == showSigRef (freeFun));
161 CHECK ("int (uint)" == showSigRef (lambda));
162 CHECK ("int (uint)" == showSigRef (f5));
163
164 CHECK ("int (uint)" == showSigCRef (freeFun));
165 CHECK ("int (uint)" == showSigCRef (lambda));
166 CHECK ("int (uint)" == showSigCRef (f5));
167
168 CHECK ("int (uint)" == showSigRRef (move(lambda)));
169 CHECK ("int (uint)" == showSigRRef (move(f5)));
170
171 CHECK ("int (uint)" == showSig (move(&freeFun)));
172 CHECK ("int (uint)" == showSig (move(lambda)));
173 CHECK ("int (uint)" == showSig (move(f5)));
174
175
176 Func& funRef = f1;
177 Functor& funkyRef = funk;
178 Func const& funCRef = f1;
179 Functor const& funkyCRef = funk;
180 CHECK ("int (uint)" == showSig (funRef));
181 CHECK ("int (uint)" == showSig (funkyRef));
182 CHECK ("int (uint)" == showSig (funCRef));
183 CHECK ("int (uint)" == showSig (funkyCRef));
184
185
186 CHECK ("int (uint)" == typeStr<_Fun<int(uint)>::Sig >());
187 CHECK ("int (uint)" == typeStr<_Fun<Func&>::Sig >());
188 CHECK ("int (uint)" == typeStr<_Fun<Func&&>::Sig >());
189 CHECK ("int (uint)" == typeStr<_Fun<Func const&>::Sig >());
190 CHECK ("int (uint)" == typeStr<_Fun<Functor&>::Sig >());
191 CHECK ("int (uint)" == typeStr<_Fun<Functor&&>::Sig >());
192 CHECK ("int (uint)" == typeStr<_Fun<Functor const&>::Sig>());
193
194 using Siggy = _Fun<Func>::Sig;
195 CHECK ("int (uint)" == typeStr<_Fun<Siggy&>::Sig >());
196 CHECK ("int (uint)" == typeStr<_Fun<Siggy&&>::Sig >());
197 CHECK ("int (uint)" == typeStr<_Fun<Siggy const&>::Sig >());
198
199
200 auto memfunP = &Functor::fun;
202 Func fMF{bind (fM, funk, _1)};
203
204 CHECK ("int (uint)" == typeStr<_Fun<decltype(memfunP)>::Sig>());
205 CHECK ("int (Functor&, uint)" == typeStr<_Fun<decltype(fM)>::Sig >());
206 CHECK ("int (uint)" == typeStr<_Fun<decltype(fMF)>::Sig >());
207
208
209 // _Fun<F> can be used for metaprogramming with enable_if
210 CHECK ( _Fun<Func>::value); // yes : a Functor
211 CHECK ( _Fun<int(long)>::value); // yes : a function type
212 CHECK (not _Fun<int>::value); // no : a type without function call operator
213
214 auto lambda1 = [](int i) { return double(i) / (i*i); };
215 auto lambda2 = [](auto i) { return double(i) / (i*i); };
216
217 using TLamb1 = decltype(lambda1);
218 using TLamb2 = decltype(lambda2);
219
220 CHECK ( _Fun<TLamb1>::value); // yes : detect signature of lambda
221 CHECK (not _Fun<TLamb2>::value); // no : can not detect signature of a generic lambda!
222
223 // but detection works, once the templated operator() has been instantiated to some fixed type
225 CHECK ( _Fun<decltype(stdFunction)>::value);
226
227 CHECK ("double (int)" == showSig (lambda1));
228 CHECK ("double (float)" == showSig (stdFunction));
229 }
230 };
231
232
235
236
237
238}}} // namespace lib::meta::test
Automatically use custom string conversion in C++ stream output.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Metaprogramming tools for detecting and transforming function types.
unsigned int uint
Definition integral.hpp:29
function< int(uint)> Func
function< int(Functor &, uint)> FuncF
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Trait template for uniform access to function signature types.
Definition function.hpp:144