C++ features by examples
11.cpp
Go to the documentation of this file.
1
14static_assert(__cplusplus == 201103, "");
15
16#include <signal.h>
17#include <unistd.h>
18#include <bits/stdc++.h>
19
20#if __has_include (<version>)
21#include <version>
22#endif
23
24using namespace std;
25
33{
34 static_assert(__cpp_decltype, "");
35
36 int a;
37 // https://en.cppreference.com/w/cpp/header/type_traits
38 decltype(a) b; // https://en.cppreference.com/w/cpp/language/decltype
39
40 assert((is_same<decltype(a), decltype(b)>::value));
41 assert((!is_same<decltype(a), unsigned>::value));
42 assert((is_same<int, int32_t>::value));
43 assert((is_same<signed, int32_t>::value));
44
45 assert(is_integral<int>::value);
46 assert(is_integral<bool>::value);
47 assert(!is_integral<float>::value);
48 assert(is_pointer<int*>::value);
49 assert(sizeof (long long) >= 8);
50}
51
53
55{
56 int d = 0;
57 unique_ptr<int> u1;
58 assert(!u1);
59 u1.reset(&d);
60 assert(u1);
61 *u1 = 1;
62 assert(d == 1);
63
64 unique_ptr<int> u2;
65 // u2 = u1; - prohibited
66
67 int * p1 = u1.get();
68 u2 = move(u1); // [move](https://en.cppreference.com/w/cpp/utility/move)
69 assert(u2.get() == p1);
70 assert(u2);
71 assert(!u1);
72 assert(u2.get() == &d);
73 // must release because d is local
74 u2.release();
75 u2.reset(new int(10));
76 assert(*u2 == 10);
77
78 u2.reset(); // deletes int(10)
79 assert(u2 == nullptr); // [nullptr](https://en.cppreference.com/w/cpp/language/nullptr)
80
81 assert(!u2);
82}
83
85
87{
88 shared_ptr<int> s1;
89 assert(!s1);
90 assert(!s1.use_count());
91
92 auto s2 = make_shared<int>(1);
93 assert(s2.use_count() == 1);
94
95 s1 = s2;
96 assert(s1.use_count() == 2);
97
98 *s1 = 2;
99 assert(*s1 == *s1.get());
100 assert(*s2 == 2);
101
102 s2 = nullptr; // like s2.reset();
103 assert(s1.use_count() == 1);
104 assert(!s2.use_count());
105}
106
108
110{
111 std::weak_ptr<int> wp;
112
113 assert(!wp.lock());
114 assert(!wp.use_count());
115 auto sp = std::make_shared<int>(1);
116 wp = sp;
117 assert(*wp.lock() == 1);
118}
119
127{
128 auto a = new int[3] {1, 2, 3};
129 assert(a[2] == 3);
130 delete[] a;
131
132 auto as = new string[3] {"1", "2", "3"};
133 assert(as[2] == "3");
134 delete[] as; // calls destructors for all members
135
137
139
140 weak_pointer();
141}
142
145
146char func_type(const int& x)
147{
148 assert(is_const<typename remove_reference<decltype(x)>::type>::value);
149 assert(is_lvalue_reference<decltype(x)>::value);
150 return 'C';
151}
152
153char func_type(int& x)
154{
155 assert(is_lvalue_reference<decltype(x)>::value);
156 return 'L';
157}
158
159char func_type(int&& x)
160{
161 assert(is_rvalue_reference<decltype(x)>::value);
162 return 'R';
163}
164
166
167template<class T>
168char func_type_template(T&& x) // x is a forwarding reference
169{
170 // x is not R-value here
171 assert(func_type(x) != 'R');
172
173 // x can be forwarded as R or L value
174 // https://en.cppreference.com/w/cpp/utility/forward
175 return func_type(forward<T>(x)); // like func_type((T)(x));
176}
177
187{
188 // https://en.cppreference.com/w/cpp/language/reference
189 assert(is_reference<int&>::value);
190
191 // L-value:
192 assert(is_lvalue_reference<int&>::value);
193
194 // R-value
195 assert(is_rvalue_reference<int&&>::value);
196
197 const int c = 1;
198 int i = 2;
199
200 assert(func_type(3) == 'R');
201 assert(func_type(c) == 'C');
202 assert(func_type(move(i)) == 'R');
203
204 assert(func_type_template(c) == 'C');
205 assert(func_type_template(i) == 'L');
206 assert(func_type_template(3) == 'R');
207 reference_wrapper<int> rw = i;
208 rw.get() = 3;
209 assert(i == 3);
210 auto cr = cref(i);
211 assert(cr == 3);
212}
213
232{
233 struct C { int a, b, c; };
234 auto o2 = C {1, 2, 3};
235 C o3 {1, 2, 3};
236 (void) o3;
237
238 auto uses_il = [](initializer_list<int> il) {
239 assert(*il.begin() == 3);
240 assert(il.size() == 4);
241 };
242 uses_il({3, 2, 1, 0});
243
244 auto z1 = C();
245 C z2 = {};
246 auto z3 = C {};
247
248 assert(!z1.a);
249 assert(!z2.a);
250 assert(!z3.a);
251 array<int, 3> a {1, 2};
252}
253
265auto auto_int = 1;
266
267// int before(int a) { return a; }
268auto trailing_return_type(int a) -> int
269{
270 return a;
271}
272
274
276{
277 struct Obj2 { Obj2* orig = this; int ballast[4]; };
278 auto&& o2 = [](){ return Obj2();}();
279 assert(&o2 == o2.orig);
280}
281
283{
284 class functor {
285 int y = 1;
286 public:
287 int operator()(int a) const {
288 return a + y;
289 }
290 };
291 functor ft;
292 assert(ft(1) == 2);
293
294 // https://en.cppreference.com/w/cpp/utility/functional/function
295 function<int(int)> ft2 = ft;
296 assert(ft(2) == 3);
297 return;
298
299 // https://en.cppreference.com/w/cpp/utility/functional/bind
300 auto binded = bind(ft2, 3);
301 assert(binded() == 5);
302
304}
305
306static_assert(__cpp_constexpr, "");
307
309
310constexpr int constexpr_factorial(int n)
311{
312 return n <= 1 ? 1 : (n * constexpr_factorial(n - 1));
313}
314
316
317template<typename T>
318T constexpr adder(T v) {
319 return v;
320}
321
322template<typename T, typename... Args>
323T constexpr adder(T first, Args... args) {
324 return first + adder(args...);
325}
326
327static_assert(adder(1,2,3) == 6,"");
328
329struct Base11
330{
331 virtual void method1();
332 virtual void method2();
333};
334
336{
337 void method1() override;
338 void method2() final;
339};
340
342
350static void lambda_basics(void)
351{
352 auto annotated_named_lambda_expression = // optional name
353 [ ] // capture clause
354 ( ) // optional list of arguments
355 { }; // body
356
357 // Primitive named lambdas are just like closure functions:
358 // https://en.wikipedia.org/wiki/Closure_(computer_programming)
359
360 // declaration like a function:
361 // void closure() { };
362 auto closure = [] { };
363
364 closure();
365
366 // with arguments
367 auto pass = [] (int a) { return a; };
368 assert(pass(5) == 5);
369
370 // lambda captures external value
371 int c = 1;
372 auto get_i = [=] () { return c; };
373 assert(get_i() == 1);
374
375 // lambda captures external variable by reference
376 // with omitted arguments and return type
377 auto inc_get = [&] { return ++c; };
378 assert(inc_get() == 2);
379 assert(inc_get() == 3);
380
381 // annotated expanded empty inline lambda call:
382 [ ] // capture
383 ( ) // optional list of arguments
384 -> void // optional return value
385 { } // body
386 ( ); // call with arguments
387
388 // annotated expanded sample inline lambda call:
389 c = // result
390 [c] // capture
391 (int a) // an argument
392 -> int // return value
393 { return c + a; } // body
394 (1); // call with argument
395 assert(c == 4);
396
397 // inline lambda which is called in place
398 // https://en.wikipedia.org/wiki/Anonymous_function
399
400 // assert((1 + 1) == 2);
401 assert([](int a) { return a + 1; }(1) == 2);
402
403 // Actually calling lambda inline is useless
404 // and is provided only for demonstration.
405}
406
408static int glob;
410
411static void lambda_capture(void)
412{
413 // read only
414 int i = 2;
415 assert([=]{return i; }() == 2);
416
417 // read and write access
418 [&](int a){i = a;}(3);
419 assert(i == 3);
420
421 // explicit r/o and r/w
422 int j;
423 [i, &j](){ j = i; }();
424 assert(j == i);
425
426 // r/o by default
427 i++;
428 [=, &j](){ j = i; }();
429 assert(j == i);
430
431 // r/w by default
432 i++;
433 [&, i](){ j = i; }();
434 assert(j == i);
435
436 // can access globals anyway
437 auto inc_global = [] () { return ++glob; };
438 assert(inc_global() == 1);
439 assert(inc_global() == 2);
440}
441
443
445{
446 // [list_initialization](https://en.cppreference.com/w/cpp/language/list_initialization)
447 vector<int> v = {1, 2, 3};
448 assert(v.data()[2] == 3);
449
450 v.shrink_to_fit();
451
452 v.emplace(v.cbegin(), 0);
453 assert(v.front() == 0);
454
455 v.emplace_back(4);
456 assert(v.back() == 4);
457
458 array<int, 1> a1, a2;
459 swap(a1, a2);
460
462 forward_list<int> fl;
463
464 fl.push_front(1);
465 assert(fl.front() == 1);
466 fl.emplace_front(2);
467 assert(fl.front() == 2);
468 fl.insert_after(fl.cbegin(), 3);
469 assert(fl.front() + 1 == 3);
470 assert(fl.front() == 2);
471 fl.erase_after(fl.cbefore_begin()); // like fl.pop_front();
472 assert(fl.front() == 3);
473 fl.pop_front();
474}
475
477
479{
480 vector<int> v = {1, 2, 3};
481 assert(find(begin(v), end(v), 0) == end(v));
482 assert(find(begin(v), end(v), 1) != end(v));
483}
484
486
488{
490
491 array<int, 10> s {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
492 sort(s.begin(), s.end(),
493 // sort using a lambda expression
494 [](int a, int b)
495 { return a > b; }
496 );
497}
498
500
507
509
510// int use_lambda(int a; int (func*)(int))
511static int use_lambda(int a, function<int(int)> f)
512{
513 // lambda argument is like pointer to functions
514 return f(a);
515}
516
517static function<int(int)> g_f;
518
519static void set_lambda(function<int(int)> &&f)
520{
521 g_f = f;
522}
523
524static int call_lambda(int a)
525{
526 return g_f(a);
527}
528
530
531static void lambda_complex(void)
532{
533 auto increment = [] (int a) -> int { return a + 1; };
534 assert(increment(5) == 6);
535
536 // named lambda as argument
537 assert(use_lambda(2, increment) == 3);
538 set_lambda(increment);
539 assert(call_lambda(3) == 4);
540
541 // inline lambda as argument
542 assert(use_lambda(1, [](int a) {return a + 1;}) == 2);
543
544 int x = 0;
545 [x] () mutable { assert(++x);}();
546 assert(x == 0);
547}
548
550
558
559// just function with delay for demonstration
560int lento(int a = 0)
561{
562 this_thread::yield();
563 this_thread::sleep_for(chrono::milliseconds(20));
564 return a;
565}
567
573{
574 mutex m;
575 bool ready;
576 condition_variable cv;
577 thread initiator([&m, &ready, &cv] {
578 unique_lock<mutex> lk(m);
579 lento();
580 lk.unlock();
581 ready = true;
582 cv.notify_one();
583 });
584 unique_lock<mutex> lk(m);
585 cv.wait(lk, [&ready] {return ready;});
586 initiator.join();
587}
588
590{
591 this_thread::yield();
592 this_thread::get_id();
593 this_thread::sleep_for(chrono::nanoseconds(1));
594 promise<int> p;
595 future<int> f = p.get_future();
596 int v = 0;
597 thread t([&p, &v]{
598 lento();
599 p.set_value(2);
600 v = 3;
601 });
602 assert(v == 0);
603 assert(f.get() == 2);
604 lento();
605 assert(v == 3);
606 thread t2;
607 t2.swap(t);
608 assert(!t.joinable());
609 assert(t2.joinable());
610 t2.join();
611 try {
612 t2.join();
613 t2.detach();
614 } catch(const system_error& e) {
615 assert(e.code().value() == 22);
616 }
617 assert(!t2.joinable());
618
619 // detach demo
620 {
621 thread t3([&p, &v]{
622 v = 4;
623 });
624 t3.detach();
625 }
626 lento();
627 assert(v == 4);
628
630}
631
633{
634 int unguarded = 0, guarded = 0;
635 mutex m;
636
637 thread t1([&unguarded, &guarded, &m]{
638 unguarded = lento(unguarded) + 1;
639
640 lock_guard<mutex> guard(m);
641 guarded = lento(guarded) + 1;
642 });
643 thread t2([&unguarded, &guarded, &m]{
644 unguarded = lento(unguarded) + 1;
645
646 lock_guard<mutex> guard(m);
647 guarded = lento(guarded) + 1;
648 });
649
650 assert(unguarded == 0);
651 assert(guarded == 0);
652 t1.join();
653 t2.join();
654 assert(unguarded == 1);
655 assert(guarded == 2);
656}
658
692void sig(int)
693{
694 abort();
695}
696
697int main(void)
698{
699 signal(SIGALRM, sig);
700 alarm(1);
702 init_11();
703 auto r = trailing_return_type(1);
704 (void) r;
708 func_11();
709 container_11();
710 algorithm_11();
711 sort_11();
713 static_assert(constexpr_factorial(4), "");
714
715 types_11();
716 threads_11();
717 mutex_11();
718
719 return 0;
720}
721
int main(void)
Definition: 11.cpp:697
void sig(int)
Definition: 11.cpp:692
static void lambda_complex(void)
Definition: 11.cpp:531
static void lambda_basics(void)
Definition: 11.cpp:350
void container_11()
container
Definition: 11.cpp:444
void algorithm_11()
algorithm
Definition: 11.cpp:478
static void lambda_capture(void)
Definition: 11.cpp:411
void sort_11()
Compare with sort_03.
Definition: 11.cpp:487
void func_11()
Definition: 11.cpp:282
void types_11()
Definition: 11.cpp:32
auto auto_int
https://en.cppreference.com/w/cpp/language/auto
Definition: 11.cpp:265
void dynamic_memory_11()
Definition: 11.cpp:126
char func_type(const int &x)
Definition: 11.cpp:146
void shared_pointer()
shared_ptr
Definition: 11.cpp:86
void copy_elision_demo()
copy_elision
Definition: 11.cpp:275
constexpr T adder(T v)
https://en.cppreference.com/w/cpp/language/parameter_pack
Definition: 11.cpp:318
constexpr int constexpr_factorial(int n)
https://en.cppreference.com/w/cpp/language/constexpr
Definition: 11.cpp:310
void init_11()
Definition: 11.cpp:231
void references_11()
Definition: 11.cpp:186
auto trailing_return_type(int a) -> int
Definition: 11.cpp:268
void weak_pointer()
weak_ptr
Definition: 11.cpp:109
void unique_pounter()
unique_ptr
Definition: 11.cpp:54
char func_type_template(T &&x)
Forwarding reference
Definition: 11.cpp:168
void threads_11()
Definition: 11.cpp:589
void mutex_11()
Definition: 11.cpp:632
void condition_variable_11()
Definition: 11.cpp:572
Definition: 11.cpp:330
virtual void method1()
virtual void method2()
void method1() override
override
void method2() final
final