C++ features by examples
20.cpp
Go to the documentation of this file.
1
15static_assert(__cplusplus >= 201707);
16
17#include <bits/stdc++.h>
18
19using namespace std;
20
27#if __cpp_lib_three_way_comparison
28static_assert(1 <=> 2 < 0 );
29static_assert(2 <=> 1 > 0 );
30static_assert(1 <=> 1 == 0 );
31#else
32#pragma message("undefined __cpp_lib_three_way_comparison")
33#endif
34
35#if __cpp_char8_t
37char8_t char8;
38#endif
39
41
42auto to_array_demo = to_array("foo");
43static_assert(to_array_demo.size() == 4);
44
45void init_20()
46{
47 struct point { int x, y; };
48 struct line { point a, b; };
49
50 // [aggregate_initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization)
51
52#if __cplusplus > 201707
53 point p1 = { .x = 1 };
54 assert(p1.x == 1);
55 assert(!p1.y);
56
57 point p2 { {} , 2 };
58 assert(p2.y == 2);
59 assert(!p2.x);
60#endif
61#if __cpp_aggregate_paren_init >= 201902
62 int a[] (0, 1, 2);
63 assert(a[2] == 2);
64 line l2 = { 1, 2 };
65 assert(l2.a.x == 1);
66 assert(l2.a.y == 2);
67#endif
68 line l1 = { };
69 assert(!l1.a.x);
70 line l3 = { 1, 2, 3, 4 };
71 assert(l3.b.x == 3);
72 assert(l3.b.y == 4);
73}
74
76{
77#if __cpp_lib_bit_cast
78 cout << typeid(bit_cast<double>(0));
79#endif
80}
81
83{
86 auto a = make_shared<int[10]>();
87 static_assert(is_same_v<decltype(a.get()), int*>);
88
90 map<int, int> m = {{2,3}};
91#if __cplusplus > 201707 && __GNUG__ > 8
92 assert(m.contains(2));
93#endif
94#if __cpp_lib_erase_if
96 vector<int> v = {11, 12, 13};
97 assert(erase_if(v, [](int a) {return a >= 13;}) == 1);
98 assert(v.size() == 2);
99#endif
100}
101
102namespace lambda {
103
104#if __cpp_template_template_args && __GNUG__ > 8
106template <typename ... Args>
107auto make_lambda_with_parameter_pack_capture(Args&& ... args)
108{
109 return [... args = forward<Args>(args)] {
110 return (... + args);
111 };
112}
113#endif
114
116{
117#if __cplusplus >= 201709
118 // generic lambda, operator() is a template with two parameters
119 auto glambda = []<class T>(T a, auto&& b) { return a < b; };
120 assert(glambda(1,2));
121 // generic lambda, operator() is a template with one parameter pack
122 auto f = []<typename ...Ts>(Ts&& ...ts) {
123 return 1;
124 };
125 assert(f(1,2,3));
126
127 struct point { int x, y; };
128 auto point_lambda = []<class T=point>(T&& var) {};
129 point_lambda({1, 2});
130
131 #if __cpp_template_template_args && __GNUG__ > 8
132 assert(make_lambda_with_parameter_pack_capture(1,2,3)() == 6);
133 #endif
134#endif
135}
136
137}
138using namespace lambda;
139
140
142
167// Using [requires](https://en.cppreference.com/w/cpp/keyword/requires)
168
169template <typename T> requires is_integral_v<T> T constexpr requires_demo(T a) { return a + 1; }
170
171static_assert(requires_demo(1) == 2);
172
177template <typename T> auto constexpr requires_demo(T && a) requires is_same_v<T, double> { return 2; }
178static_assert(requires_demo(0.1) == 2);
179
180// Annotated example of complex requirement
181template <class T>
182requires // requires-clause
183is_signed_v<T> || (is_unsigned_v<T> && ! is_void_v<void>) // constraint expression
185
187
188template < class T >
189requires // requires-clause
190requires() // requires-expression
191{ true;} // unevaluated requirements sequence
193
194template <class T> requires requires(T a) { a / 0; } auto constexpr what(T a) { return 1; }
195static_assert(what(1) == 1);
196
197template <class T> requires requires(T a) { a[0]; } auto constexpr what(T a) { return 2; }
198static_assert(what("2") == 2);
199
200
209template <typename T> concept truism = true;
210
211#if !__cpp_lib_concepts
212
214template <class T> concept integral = is_integral_v<T>;
215
216#endif
217
222template <class T> concept integral_req_ct = requires (T a) { is_integral_v<T>; };
223
224template <integral_req_ct T> constexpr T _inc2(T a) { return a + 1; }
225
226static_assert(_inc2(1) == 2);
227
233template<typename T> concept compound_requirements =
234requires(T x) {
235 {x + 1} -> convertible_to<bool>;
236 {x * 2} -> same_as<int>;
237};
238
239
240
258#if __cpp_impl_coroutine
259auto switch_to_new_thread(jthread& out)
260{
261 struct awaitable {
262 jthread* p_out;
263 bool await_ready() { return false; }
264 void await_suspend(coroutine_handle<> h) {
265 jthread& out = *p_out;
266 if (out.joinable())
267 throw runtime_error("Output jthread parameter not empty");
268 out = jthread([h] { h.resume(); });
269 }
270 void await_resume() {}
271 };
272 return awaitable{&out};
273}
274
275struct task {
276 struct promise_type {
277 struct task get_return_object() { return {}; }
278 suspend_never initial_suspend() { return {}; }
279 suspend_never final_suspend() noexcept { return {}; }
280 void return_void() {}
281 void unhandled_exception() {}
282 };
283};
284
285struct task resuming_on_new_thread(jthread& out)
286{
287 auto starting_tid = this_thread::get_id();
288 // suspends coroutine
289 co_await switch_to_new_thread(out);
290 // awaiter is destroyed here
291 assert(this_thread::get_id() != starting_tid);
292}
293
294void coroutine_demo()
295{
296 jthread out;
297 resuming_on_new_thread(out);
298}
299#else
301#pragma message("undefined __cpp_impl_coroutine")
302#endif
303
317#if __cpp_lib_ranges
318
319#include <ranges>
320
325
326void sort_20()
327{
328 vector<int> v = {5, 7, 4, 2, 8, 6, 1, 9, 1, 3};
329 ranges::sort(v);
330 assert(v.front() <= v.back());
331 assert(ranges::distance(v));
332 assert(!ranges::distance(v.begin(), v.begin()));
333}
334
335void ranges_20()
336{
337 auto data = {0, 1, 2, 3};
339#if __clang_major__ != 10
340 ranges::reverse_view rv {data};
341 auto r = data | views::reverse;
342 // r is kind of transform_view
343 vector result(r.begin(), r.end());
344 assert(vector(rv.begin(), rv.end()) == result);
345 assert((result == vector{3, 2, 1, 0}));
346#endif
347 auto [min, max] = ranges::minmax({3, 2, 1});
348 auto a = ranges::minmax({3, 2, 1});
349 assert(min == 1);
350 assert(max == 3);
351 assert(!in_range<std::size_t>(-1));
352}
353
354#else
355#pragma message("undefined __cpp_lib_ranges")
356#endif
357
358#include <experimental/source_location>
359
361
363{
364 auto l = experimental::source_location::current();
365 basic_stringstream<char> buff;
366 buff << l.file_name() << ":" << l.line() << ":" << l.column() << l.function_name();
367 assert(buff.str().length());
368}
369
376{
377 auto constexpr plus_one = std::bind_front(std::plus<int>(), 1);
378 static_assert(plus_one(2) == 3);
379}
380
382
383int main()
384{
385 init_20();
386 types_20();
388 lambda_20();
389#if __cpp_lib_jthread
390 jthread t([]{ });
391#endif
393 sort_20();
394 ranges_20();
395 location_20();
397}
399
short concept definition from a constraint directly
Definition: 20.cpp:214
trivial concepts as assignment
Definition: 20.cpp:209
int main()
Definition: 20.cpp:383
void coroutine_demo()
Definition: 20.cpp:300
void types_20()
Definition: 20.cpp:75
void dynamic_memory_20()
Definition: 20.cpp:82
void init_20()
Definition: 20.cpp:45
auto to_array_demo
to_array
Definition: 20.cpp:42
void functional_20()
Definition: 20.cpp:375
void location_20()
source_location
Definition: 20.cpp:362
void complex_requirement_demo()
Definition: 20.cpp:184
void requires_expression_demo()
Annotated example of requires-expression.
Definition: 20.cpp:192
constexpr auto what(T a)
Definition: 20.cpp:194
constexpr T requires_demo(T a)
Definition: 20.cpp:169
Definition: 20.cpp:102
void lambda_20()
Definition: 20.cpp:115