-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathDemo.cpp
More file actions
328 lines (305 loc) · 17.3 KB
/
Demo.cpp
File metadata and controls
328 lines (305 loc) · 17.3 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
/////////////////////////////////////////////////////////////////////////////
// LICENSE NOTICE
// --------------
// Copyright (c) Hexadigm Systems
//
// Permission to use this software is granted under the following license:
// https://www.hexadigm.com/GenericLib/License.html
//
// This copyright notice must be included in this and all copies of the
// software as described in the above license.
//
// DESCRIPTION
// -----------
// For complete details on "FunctionTraits" (fully documented), see
// https://github.com/HexadigmSystems/FunctionTraits
//
// This file contains a small demo program highlighting the capabilities of
// the "FunctionTraits" library declared in "FunctionTraits.h" (see above
// link), a collection of templates used to retrieve and/or modify any
// component of a C++ function (return type, argument types, cv-qualifiers,
// noexcept specification, etc. - all components comprising a C++ function
// are available, and write traits to modify these components are also fully
// supported though not demo'd in this program - read on to find examples).
//
// Just run the program to display all available traits for the 3 sample
// functions seen in namespace "TestFuncs" later in this file (traits
// displayed to the stdout). You can update these 3 functions with any
// signature whose traits you want to display and re-run the app (or
// experiment with any other template in the library - again, read on).
//
// Note however that all 3 sample functions are simply passed to the
// (function) template "DisplayAllFunctionTraits()" in the library itself,
// which displays all traits for any function type you pass (via its
// template arg "F" - see
// https://github.com/HexadigmSystems/FunctionTraits/#displayallfunctiontraits
// for details). You can therefore just call "DisplayAllFunctionTraits()"
// directly if you wish, passing any function type you want for its template
// arg "F" (free functions which includes static member functions, pointers
// and references to free functions, references to pointers to free
// functions, non-static member function pointers or references to them,
// functors including lambdas, "abominable" functions and "std::function"
// specializations).
//
// Note that other examples of how to use the library (including write
// traits) are also available at the library's link above. See the "Usage"
// section there for full details. You can copy these (usage) examples into
// function "main()" if you wish (see examples here:
// https://github.com/HexadigmSystems/FunctionTraits/#technique2of2examples),
// or experiment with any other template in the library, relying on
// "DisplayAllFunctionTraits()" whenever you want to display a function's
// complete traits (in fact, you can even inspect the latter function itself
// as a good learning exercise if you wish, since it's written as a client
// of the library itself, no different than your own code will be - tracing
// into it therefore shows what can be accomplished but you don't need to
// trace into any of the library's other implementation details, which would
// be an arduous and unnecessary task).
//
// Note that "DisplayAllFunctionTraits()" is particularly useful when
// testing the library's write trait templates so you can see the results of
// changing any component of a C++ function (say, if you call "ReplaceArg_t"
// to replace (change) a function's existing parameter type, you can then
// just pass the resulting function type returned by "ReplaceArg_t" to
// "DisplayAllFunctionTraits()" in order to see the change). Also see
// "TypeName_v" in the library for converting any C++ type to its
// user-friendly string equivalent, which is also very useful when you just
// want to display a C++ type (so in the case of the "ReplaceArg_t" example
// just described for instance, you can pass the type it returns to
// "TypeName_v" to convert it to a string for display purposes). See
// "TypeName_v" here for details:
// https://github.com/HexadigmSystems/FunctionTraits/#typename_v
//
// A brief summary of the library's main templates can be found here
// (grouped so you can quickly see which templates target each component of
// a C++ function type, from return type to noexcept):
//
// Summary of templates in this library
// https://github.com/HexadigmSystems/FunctionTraits#summaryoftemplatesinthislibrary
//
// And the complete documentation of all templates can be found here (in
// alphabetical order grouped by read and write traits):
//
// Helper templates (complete, alphabetical list)
// https://github.com/HexadigmSystems/FunctionTraits#helpertemplates
//
// Lastly, note that within Compiler Explorer (the hosting site for this
// demo), the program defaults to C++20. If you wish to change this then add
// -DCMAKE_CXX_STANDARD=?? to the CMake command line options in Compiler
// Explorer, setting "??" in the latter option to the target C++ version
// (17, 20, 23 or beyond - versions prior to C++17 are not supported). In
// Compiler Explorer, the CMake command line options are normally located
// near the top-left corner of the source code window on the left, just
// above the project name "FunctionTraitsDemo", so add just the
// -DCMAKE_CXX_STANDARD=??" option there. For further details on the CMake
// command line options for this demo (though most users don't need to get
// involved with these), see the top of the "CMakeLists.txt" file in the
// Compiler Explorer source code window.
/////////////////////////////////////////////////////////////////////////////
// #included first so we can check CPP17_OR_LATER just below
#include "CompilerVersions.h"
// We only support C++17 or later (stop compiling otherwise)
#if CPP17_OR_LATER
////////////////////////////////////////////////////////////
// "import std" not currently in effect? (C++23 or later).
// If it is in effect then no need to #include the headers
// below (they're already available)
////////////////////////////////////////////////////////////
#if !defined(STDEXT_IMPORTED_STD)
// Standard C/C++ headers
#include <cstddef>
#include <iostream>
#include <string>
#include <string_view>
#endif
////////////////////////////////////////////////////////
// Our headers (only file in this repository you need
// to explicitly #include)
////////////////////////////////////////////////////////
#include "FunctionTraits.h"
/////////////////////////////////////////
// Everything in "FunctionTraits.h" just
// above declared in this namespace
/////////////////////////////////////////
using namespace StdExt;
/////////////////////////////////////////////////////////////////////////////
// "DisplayFunctionTraits()"
/////////////////////////////////////////////////////////////////////////////
template <typename F>
void DisplayFunctionTraits(tstring_view caption)
{
// Display the caption for this function to the stdout
tcout << _T("************************************\n");
tcout << _T("* ") << caption << _T("\n");
tcout << _T("************************************\n");
/////////////////////////////////////////////////
// Stream the function's traits to "tcout". The
// following function from the "FunctionTraits"
// library itself does all the work. See here
// for details:
//
// https://github.com/HexadigmSystems/FunctionTraits#DisplayAllFunctionTraits
/////////////////////////////////////////////////
DisplayAllFunctionTraits<F>(tcout);
}
//////////////////////////////////////////////////////////////////////////////
// namespace TestFuncs. Contains 3 functions whose traits this demo displays.
// Functions need not be defined in any namespace however (for this demo to
// work). Doing so just to keep things organized (and placed in this
// namespace for easy access - you can quickly change all functions in this
// one location). Note that you can experiment with this program by simply
// changing the signatures of these functions to whatever you wish and
// re-running the app (but don't change the function names themselves unless
// you also change them where they're actually used later on, though there's
// normally no need to - the function signature is all that matters, not the
// name).
//////////////////////////////////////////////////////////////////////////////
namespace TestFuncs
{
//////////////////////////////////////////////////////
// Free function. Note: Need not be defined for this
// demo to work and it's not (only the function's
// type matters)
//////////////////////////////////////////////////////
int FreeFunc(const std::wstring &, const char *, short, int, float, long, double, ...) noexcept;
class SomeClass
{
public:
////////////////////////////////////////////////////
// Temporarily disable warnings about unsupported
// calling conventions so that STDEXT_CC_STDCALL
// just below won't trigger any such warnings (when
// building for platforms that don't support this
// calling convention - it's normally supported on
// x86-32 only). GCC, Clang and Intel (oneAPI) for
// for instance would display a warning for all
// builds except x86-32 (though MSFT doesn't - it
// just quietly ignores it normally).
////////////////////////////////////////////////////
DIAGNOSTIC_PUSH_AND_IGNORE_UNSUPPORTED_CC_WARNINGS
//////////////////////////////////////////////////////
// Non-static member function (static functions also
// supported but processed like a free function so
// the one above is used). Note: Need not be defined
// for this demo to work and it's not (only the
// function's type matters)
//////////////////////////////////////////////////////
int STDEXT_CC_STDCALL DoSomething(double &, const std::string_view &) const volatile && noexcept;
///////////////////////////////////////////////////
// Restore unsupported calling convention warnings
// disabled above
///////////////////////////////////////////////////
DIAGNOSTIC_POP_IGNORE_UNSUPPORTED_CC_WARNINGS
///////////////////////////////////////////////////
// Adding this to make the class a functor (which
// are also supported)
///////////////////////////////////////////////////
std::basic_string<tchar> operator()(std::size_t) const;
};
}
//////////////////////////////////////////////////////////////////////////////
// DisplayFreeFunctionTraits()
//////////////////////////////////////////////////////////////////////////////
void DisplayFreeFunctionTraits()
{
////////////////////////////////////////////////////////////
// Free function type or static member function type whose
// traits we wish to display (non-static member functions
// are handled by "DisplayMemberFunctionTraits()" below).
// Note that pointers or reference to the function are also
// supported, as well as references to function pointers.
// The following is the actual (raw) function type however,
// neither pointer nor reference, though most developers
// don't work with the actual function type in code too
// often (since function names decay to a pointer to the
// function in most scenarios so pointers to functions are
// much more common in most code - "FunctionTraits" will
// handle any legal type that identifies the function
// however, whether the function's actual (raw) C++ type,
// or pointers or references to functions, or references
// to pointers to functions)
////////////////////////////////////////////////////////
using F = decltype(TestFuncs::FreeFunc);
// using F = decltype(&TestFuncs::FreeFunc); // Will also work (pointer to function and usually
// more common in practice)
// using F = decltype(TestFuncs::FreeFunc) &; // Will also work (lvalue reference to function,
// though rvalue works too - both are rare in
// practice though, noting that this particular
// "decltype" syntax is even more rare - usually
// you'll work with a reference to the function
// in code instead, such as "int (&)()" for
// example (reference to a function taking no
// args and returning an "int"), preferably
// using an alias to simplify the latter
// (cryptic) syntax
DisplayFunctionTraits<F>(_T("Free function traits demo"));
}
//////////////////////////////////////////////////////////////////////////////
// DisplayMemberFunctionTraits()
//////////////////////////////////////////////////////////////////////////////
void DisplayMemberFunctionTraits()
{
///////////////////////////////////////////////////////////
// Non-static member function type whose traits we wish to
// display. Always a member function pointer (references
// to member function pointers also supported), unlike the
// free function version in "DisplayFreeFunctionTraits()"
// above, which supports the function's actual (raw) C++
// type as well. We don't support the raw C++ type for
// non-static member functions however, just member
// function pointers only (or references to such pointers).
// To this end, when passing a raw function type, it's
// always assumed to be a free function (which for our
// purposes also includes static member functions).
///////////////////////////////////////////////////////////
using F = decltype(&TestFuncs::SomeClass::DoSomething);
DisplayFunctionTraits<F>(_T("Member function traits demo"));
}
//////////////////////////////////////////////////////////////////////////////
// DisplayFunctorTraits()
//////////////////////////////////////////////////////////////////////////////
void DisplayFunctorTraits()
{
///////////////////////////////////////////////////////
// Functor type whose traits we wish to display. For
// functors, "F" must always be the class type itself,
// where the class has a single member function called
// "operator()" (by definition of a functor). Note
// that overloads of "operator()" are ambiguous
// however so aren't supported (a compiler error will
// result). If the function has overloads of this
// member (rare), then you should take the address of
// the overload you're interested in and use that
// instead (i.e., just a normal non-static member
// function pointer to that overload). In fact, even
// for functors with just one "operator()" member
// (like the following example), "operator()" is still
// just a member function no different than any other,
// so internally "FunctionTraits" defers to the member
// function specialization by simply targeting
// "&F::operator()"
///////////////////////////////////////////////////////
using F = TestFuncs::SomeClass;
DisplayFunctionTraits<F>(_T("Functor traits demo"));
}
/////////////////////////////////////////////////////////////////////////////
// main()
/////////////////////////////////////////////////////////////////////////////
int main()
{
tcout << _T("FunctionTraits demo (detected compiler: ") << GetCompilerName() << _T("). See top of \"Demo.cpp\" for details.\n");
tcout << _T("For complete details on \"FunctionTraits\" see https://github.com/HexadigmSystems/FunctionTraits\n\n");
DisplayFreeFunctionTraits();
tcout << _T("\n\n");
DisplayMemberFunctionTraits();
tcout << _T("\n\n");
DisplayFunctorTraits();
////////////////////////////////////////////////
// You can test any of the library's templates
// here (commenting out or removing above code
// if you wish). See top of file for details.
////////////////////////////////////////////////
return 0;
}
#else
#error "This program is only supported in C++17 or later (an earlier version was detected). Please set the appropriate compiler option to target C++17 or later and try again (minimum of "-std=c++17" for GCC, Clang and Intel, or "/std:c++17" for Microsoft)"
#endif // #if CPP17_OR_LATER