forked from grantrostig/cpp_by_example
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmain.cpp
More file actions
320 lines (291 loc) · 15.5 KB
/
main.cpp
File metadata and controls
320 lines (291 loc) · 15.5 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
/** Copyright (c) Grant Rostig, grantrostig.com 2023. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
NOT PRODUCTION QUALITY CODE, just shows learning/teaching example, not real programming, don't copy this style, just playing around
Reminder of usefull resources:
https://coliru.stacked-crooked.com/
https://godbolt.org/
https://cppinsights.io/
https://Wandbox.org
https://cpp.sh/
https://quick-bench.com/
https://arnemertz.github.io/online-compilers/
[[maybe_unused]] int * my_new_var8 = ::new (22,int);
Language Versions: clan++ -std=c++2b, g++ -std=c++23 or =gnu++23
STD Libraries: Gcc: libstdc++; Clang: libc++; Microsoft: msvc/ms stl // TODO??: how do we link with different libraries than the default using gcc or clang (the exact command line text)?
g++ -Werror -Weffc++ -Wextra -Wall -Wconversion -Wshadow -Wpedantic -Wold-style-cast -Wsign-promo -Wzero-as-null-pointer-constant -Wsuggest-override -Wnon-virtual-dtor \
-Wcast-align -Woverloaded-virtual -Wunused -pedantic -Wsign-conversion -Wmisleading-indentation -Wnull-dereference -Wdouble-promotion -Wformat=2 -Wimplicit-fallthrough \
-Wuseless-cast -Wsuggest-final-types -Wsuggest-final-methods -Wduplicated-cond -Wduplicated-branches -Wlogical-op -std=gnuc++23 \
main.cpp <OTHER>.cpp -o <A.OUT>
SYMBOL MEANING // for debugging purposes
TODO: the principal programmer needs todo.
TODO?: the principal programmer is not sure about something, that should be addressed.
TODO?:X the X programmer is not sure about something, that should be addressed.
TODO??: is a question for verbal discussion at CppMSG.com meetup meetings.
define NDEBUG if asserts are NOT to be checked. Put in *.h file not *.CPP
#define NDEBUG
define GR_DEBUG if we/programmer is Debugging. Put in *.h file not *.CPP
#define GR_DEBUG
#ifdef GR_DEBUG
#endif GR_DEBUG
*/
//#include "global_entities.h"
#include <gsl/gsl> // sudo dnf install guidelines-support-library-devel
//#include <bits/stdc++.h>
#include <chrono>
#include <cassert>
#include <csignal>
#include <iostream>
#include <source_location>
#include <string>
#include <stacktrace>
#include <vector>
using std::cin; using std::cout; using std::cerr; using std::clog; using std::endl; using std::string; // using namespace std;
using namespace std::string_literals;
using namespace std::chrono_literals;
// Some crude logging that prints source location, where X prints a variable, and R adds \n\r (which is usefull when tty in in RAW or CBREAK mode. Requires C++20.
#define LOGGER_( msg ) using loc = std::source_location;std::cout.flush();std::cerr.flush();std::cerr<< "["<<loc::current().file_name()<<':'<<std::setw(4)<<loc::current().line()<<','<<std::setw(3)<<loc::current().column()<<"]`"<<loc::current().function_name()<<"`:" <<#msg<< "." <<endl;cout.flush();cerr.flush();
#define LOGGER_R( msg ) using loc = std::source_location;std::cout.flush();std::cerr.flush();std::cerr<<"\r\n["<<loc::current().file_name()<<':'<<std::setw(4)<<loc::current().line()<<','<<std::setw(3)<<loc::current().column()<<"]`"<<loc::current().function_name()<<"`:" <<#msg<< ".\r\n"<<endl;cout.flush();cerr.flush();
#define LOGGERX( msg, x)using loc = std::source_location;std::cout.flush();std::cerr.flush();std::cerr<< "["<<loc::current().file_name()<<':'<<std::setw(4)<<loc::current().line()<<','<<std::setw(3)<<loc::current().column()<<"]`"<<loc::current().function_name()<<"`:" <<#msg<<".:{"<<x<<"}." <<endl;cout.flush();cerr.flush();
#define LOGGERXR( msg, x)using loc = std::source_location;std::cout.flush();std::cerr.flush();std::cerr<<"\r\n["<<loc::current().file_name()<<':'<<std::setw(4)<<loc::current().line()<<','<<std::setw(3)<<loc::current().column()<<"]`"<<loc::current().function_name()<<"`:" <<#msg<<".:{"<<x<<"}.\r\n"<<endl;cout.flush();cerr.flush();
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
/** Requires that a type has insertion operator
Concept definition - used by a template below.
Some value needs to be incorporated with above text:
/// Concept using Function Explicit instantiations that are required to generate code for linker.
/// TODO??: is the only used if definition is in *.cpp file?
/// https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
/// https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
//template std::ostream & operator<<( std::ostream & , std::vector<std::string> const & );
/// Concept using Function Explicit instantiations that are required to generate code for linker.
//template std::ostream & operator<<( std::ostream & , std::deque<int> const & );
*/
template <typename Container>
concept Insertable = requires( std::ostream & out ) {
requires not std::same_as<std::string, Container>; // OR $ std::is_same <std::string, Container>::value OR std::is_same_v<std::string, Container>;
{ out << typename Container::value_type {} } -> std::convertible_to<std::ostream & >; // OR just $ { out << typename Container::value_type {} };
};
/** Prints contents of a container such as a vector of int's.
Insertable Concept used by Templated Function definition
Older version is here for the record:
template<typename T> std::ostream & operator<<(std::ostream & out, std::vector<T> const & v) { // utility f() to print vectors
if ( not v.empty() ) {
out<<'['; std::copy(v.begin(), v.end(), std::ostream_iterator<T>(out, ", ")); out<<"\b\b]";
}
return out;
}
*/
template<typename Container> //template<insertable Container> // OR these 2 lines currently being used.
requires Insertable<Container>
std::ostream &
operator<<( std::ostream & out, Container const & c) {
if ( not c.empty()) {
out << "[<"; //out.width(9); // TODO??: neither work, only space out first element. //out << std::setw(9); // TODO??: neither work, only space out first element.
std::copy(c.begin(), c.end(), std::ostream_iterator< typename Container::value_type >( out, ">,<" ));
out << "\b\b\b>]"; out.width(); out << std::setw(0);
} else out << "[CONTAINTER IS EMPTY]";
return out;
}
namespace Detail { // NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
std::string source_loc(); // forward declaration
extern void stacktrace_register();
void crash_signals_register();
/** gives a source location for printing. Used for debugging. */
std::string
source_loc() {
using loc = std::source_location;
//using ts = std::to_string; // todo??: why not? alternative approach?
std::string result {"\n"s+loc::current().file_name() +":"s +std::to_string(loc::current().line()) +std::to_string(loc::current().column())+"]`"s +loc::current().function_name()+"`."s};
return result;
}
/** Called as we try to ABORT ) after already getting another signal from the application code.
OR should we exit() or terminate() and not use this function? */
auto crash_tracer_SIGABRT(int signal_number) -> void {
//LOGGERX( "We are getting out and that generated another signal, presumably ABRT, we got signal number", signal_number);
//LOGGERX( "IGNORE THIS ONE, just shown for understanding:", std::stacktrace::current());
LOGGER_( "### This is the very end! ###");
return;
}
/** Prints a stack trace of crash location. Used for debugging. */
auto crash_tracer(int signal_number) -> void {
cerr << "\n\r:CRASH_ERROR:Got signal number:" << signal_number;
cerr << "\n\r:./stack_trace::current():" << std::stacktrace::current() <<":END CRASH_ERROR STACK_TRACE."<<endl;
if ( bool is_want_prompt{true}; is_want_prompt ) {
std::string reply; cout << "CRASH_ERROR: q for exit(1) or CR to continue:"; cout.flush(); cin.clear();
getline( cin, reply );
if ( reply == "q" )
exit(1);
else
return;
}
else {
/* IGNORE using namespace std::chrono_literals;
std::chrono::duration my_duration = 2s;
cerr << "Wait time:" << 2s << " + in variable:"<< my_duration <<endl;
std::this_thread::sleep_for( my_duration ); // sleep(2); // seconds
std::this_thread::sleep_for( std::chrono_literals::s::1 ); //todo??: how to do this?
LOGGER_LOC( my_tracer(): Now- after stacktrace documenting a catastrophic error- we need to abort().);
*/
//std::signal( SIGABRT, SIG_DFL ); // repair normal signals in preparation for abort() // OR maybe?? $ std::signal( SIGABRT, SIG_IGN );
std::abort(); // OR alternatively? $ std::exit(42) or teminate, or quick_exit()??
// *** we never get here
assert( false && "Doing something after std::abort() is ERROR.\n" );
return;
}
}
/** signals that cause "terminate" and sometimes "core dump" https://en.wikipedia.org/wiki/Signal_(IPC)
We define here all the signal names listed in POSIX (1003.1-2008);
as of 1003.1-2013, no additional signals have been added by POSIX.
We also define here signal names that historically exist in every
real-world POSIX variant (e.g. SIGWINCH).
Signals in the 1-15 range are defined with their historical numbers.
For other signals, we use the BSD numbers.
There are two unallocated signal numbers in the 1-31 range: 7 and 29.
Signal number 0 is reserved for use as kill(pid, 0), to test whether
a process exists without sending it a signal.
ISO C99 signals.
#define SIGINT 2 Interactive attention signal.
#define SIGILL 4 Illegal instruction.
#define SIGABRT 6 Abnormal termination.
#define SIGFPE 8 Erroneous arithmetic operation.
#define SIGSEGV 11 Invalid access to storage.
#define SIGTERM 15 Termination request.
Historical signals specified by POSIX.
#define SIGHUP 1 Hangup.
#define SIGQUIT 3 Quit.
#define SIGTRAP 5 Trace/breakpoint trap.
#define SIGKILL 9 Killed.
#define SIGPIPE 13 Broken pipe.
#define SIGALRM 14 Alarm clock.
Adjustments and additions to the signal number constants for most Linux systems.
#define SIGSTKFLT 16 Stack fault (obsolete).
#define SIGPWR 30 Power failure imminent.
Historical signals specified by POSIX.
#define SIGBUS 7 Bus error.
#define SIGSYS 31 Bad system call.
New(er) POSIX signals (1003.1-2008, 1003.1-2013).
#define SIGURG 23 Urgent data is available at a socket.
#define SIGSTOP 19 Stop, unblockable.
#define SIGTSTP 20 Keyboard stop.
#define SIGCONT 18 Continue.
#define SIGCHLD 17 Child terminated or stopped.
#define SIGTTIN 21 Background read from control terminal.
#define SIGTTOU 22 Background write to control terminal.
#define SIGPOLL 29 Pollable event occurred (System V).
#define SIGXFSZ 25 File size limit exceeded.
#define SIGXCPU 24 CPU time limit exceeded.
#define SIGVTALRM 26 Virtual timer expired.
#define SIGPROF 27 Profiling timer expired.
#define SIGUSR1 10 User-defined signal 1.
#define SIGUSR2 12 User-defined signal 2.
Nonstandard signals found in all modern POSIX systems
(including both BSD and Linux).
#define SIGWINCH 28 Window size change (4.3 BSD, Sun).
Archaic names for compatibility.
#define SIGIO SIGPOLL I/O now possible (4.2 BSD).
#define SIGIOT SIGABRT IOT instruction, abort() on a PDP-11.
#define SIGCLD SIGCHLD Old System V name
#define __SIGRTMIN 32
#define __SIGRTMAX 64
*/
auto crash_signals_register() -> void {
std::signal( SIGHUP, crash_tracer );
std::signal( SIGINT, crash_tracer );
std::signal( SIGQUIT, crash_tracer );
std::signal( SIGILL, crash_tracer );
std::signal( SIGTRAP, crash_tracer );
std::signal( SIGABRT, crash_tracer_SIGABRT );
std::signal( SIGSEGV, crash_tracer );
}
} // End Namespace NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
// ++++++++++++++++ EXAMPLEs begin ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class Simple_class {
void what_i_want_to_run();
};
class Another_class {};
class IAbstract_Class {
public:
int i_int_{0};
string i_str{};
virtual ~IAbstract_Class() {}
virtual void iabstract_class_member_function()=0;
};
class Base_class : public IAbstract_Class {
public:
int b_int_ {0};
string i_str{};
virtual ~Base_class() override {
cout << "Base_class::~ running\n";
}
virtual void iabstract_class_member_function() override {
cout << "Base_class::IAbstract_Class_member_function(): running\n";
}
virtual void my_base_member_function() {
cout << "Base_class::My_base_member_function(): running\n";
}
};
class Derived_class1 : public Base_class {
public:
int d1_int_ {33};
string i_str{};
virtual ~Derived_class1() final {
cout << "Derived_class1::~ running\n";
}
virtual void iabstract_class_member_function() final {
cout << "Derived_class1::IAbstract_Class_member_function(): running\n";
}
virtual void my_derived_member_function() {
cout << "Derived_class1::My_derived_member_function(): running\n";
}
};
class Derived_class2 : public Base_class {
int d2_int_ {0};
public:
virtual ~Derived_class2() final {
cout << "Derived_class2::~ running\n";
}
virtual void iabstract_class_member_function() final {
cout << "Derived_class2::IAbstract_Class_member_function(): running\n";
}
virtual void my_derived_member_function() {
cout << "Derived_class2::My_derived_member_function(): running\n";
}
};
int main(int argc, char* arv[]) { string my_arv{*arv}; cout << "~~~ argc, argv:"<<argc<<","<<my_arv<<"."<<endl; cin.exceptions( std::istream::failbit); Detail::crash_signals_register();
/* unique_ptr< IAbstract_Class > interface_ptr( new IAbstract_Class ); // compile error: abstract type cannot be instanciated.
// unique_ptr< IAbstract_Class > interface_class_uptr ( new Base_class );
// unique_ptr< IAbstract_Class > interface_class_uptr2 ( new Derived_class1 );
// interface_class_uptr->iabstract_class_member_function();
// unique_ptr< Base_class > base_class_uptr( new Base_class );
// base_class_uptr->iabstract_class_member_function();
// // IAbstract_Class * base_class_ptr( new Base_class ); // different from {}?
// Base_class * base_class_ptr { new Base_class };
// base_class_ptr->my_base_member_function();
// unique_ptr< IAbstract_Class > derived_class_uptr( new Derived_class1 );
// derived_class_uptr->iabstract_class_member_function();
// // (Derived_class1 *) interface_class_uptr2->iabstract_class_member_function();
//std::vector< IAbstract_Class * > vec { */
std::vector< IAbstract_Class * > vec {
new Derived_class1 (),
new Derived_class2 (),
new Derived_class1 (),
nullptr
// , new Another_class()
};
/*std::vector< std::unique_ptr<IAbstract_Class> > vec {
//std::make_unique< Derived_class1 >(),
//std::make_unique< Derived_class2 >(),
//std::make_unique< Derived_class1 >(),
//}; */
for (auto i = vec.begin(); i != vec.end(); i++) {
// (*i).get()->iabstract_class_member_function();
(*i)->iabstract_class_member_function();
/* auto ptr = dynamic_cast<Derived_class1 *>((*i));
if (ptr) ptr->my_derived_member_function(); else cout << "can't be null, but Alan made his point.\n";
auto ptr2 = dynamic_cast<Derived_class2 *>((*i));
if (ptr2) ptr2->my_derived_member_function(); else cout << "can't be null, but Alan made his point\n.";
cout << "+++++++++++++++++++++++\n";
*/
//delete (*i);
}
cout << "###" << endl;
return EXIT_SUCCESS;
}