forked from rrrgh/exercise
-
Notifications
You must be signed in to change notification settings - Fork 0
/
c++_short_fragment_wiki.isocpp
154 lines (152 loc) · 7.28 KB
/
c++_short_fragment_wiki.isocpp
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
https://isocpp.org/wiki/faq/wg21
⓪
// Not C++ yet, but am committed to being able to do in a future version of C++ efficiently, and with no extra copies.
vector<tuple<Machine, Job>> pickMachines(vector<Machine>&& machines,
vector<Job>&& jobs) {
return zip(reverse(sort(machines, by([](const Machine& m) { return m.load(); }))),
sort(jobs, by([](const Job& j) { return j.cost(); })));
}
①
void run_threads() {
std::thread t1(f1,100);
std::thread t2([](){ f1(200); });
t1.join();
t2.join();
}
②
template <typename T> inline T minimum(const T& t) { return t; }
template <typename T, typename ...P>
inline auto minimum(const T& t, const P& ...p)
{
using res_type= std::common_type_t<T, P...>;
return std::min(res_type(t), res_type(minimum(p...)));
}
This little function template allows us to compute the minimum of an arbitrary number of values of different types. This is not rocket science but a cute example of how C++11 is more powerful than (most?) other languages and C++03. You are invited to try it. Unlike C++11, in C++14 we no longer need the redundant declaration of the result type and the more cumbersome common_type trait which we replaced thanks to auto return type deduction and common_type_t in C++14.”
③
I would like to standardize shared (read/write) locking and I/O for the chrono durations.
std::shared_mutex mut; // proposed
std::condition_variable_any cv;
...
void get_data() {
std::shared_lock<shared_mutex> sl(mut); // proposed
// mut is locked here
// ...
while (not_ready_to_proceed()) cv.wait(sl); // mut unlocked while waiting
// mut is locked here
// ...
} // mut.unlock_shared()
The above code is locking a read/write mutex in read mode and then waiting on a condition variable with that read/write mutex. Try doing that in POSIX! And yet this is all implemented on top of POSIX mutexes and condition variables, and is exception-safe as well.
④
class Stopwatch {
using clock = std::chrono::high_resolution_clock;
bool is_running() const { return stop_time_ == clock::time_point::min(); }
clock::time_point end_time() const { return is_running() ? clock::now() : stop_time_; }
clock::time_point begin_time_{clock::now()}, stop_time_{clock::time_point::min()};
public:
void stop() { if (is_running()) stop_time_ = clock::now(); }
clock::duration elapsed() const { return end_time() - begin_time_; }
};
⑤
template<typename T, size_t Size> T* begin(T (& array)[Size]) { return array; }
template<typename T, size_t Size> T* end (T (& array)[Size]) { return array + Size; }
This is just a lovely way to get hold of iterators for built-in arrays.
⑥
result_type function_name( parameter_list... )
{
claim proper( parameters... );
// No undefined behavior so far!
implementation;
claim proper( parameters... );
claim proper( result );
claim destructible( result ); // When result_type is an object type
// No undefined behavior so far!
}
That’s not C++ yet. It’s an abbreviated version of my candidate for the basic interface to a function; for details, you can look up my lecture “What is the basic interface?”
⑦
The following is a trivial use of my Boost.Proto library for building Domain-Specific Languages in C++. It builds a tree representing an expression, and then pretty-prints the tree to the standard output stream.
#include <iostream>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
int main()
{
// Create a Proto terminal that wraps a string.
// Let's be cheeky and call it "cout_".
proto::literal< char const * > cout_( "cout" );
// Create an expression tree and pass it to display_expr
// for pretty-printing.
proto::display_expr(
cout_ << "hello" << ' ' << "proto!"
);
}
Expression templates don’t seem so hard now, do they?
⑧
This is the inner loop for Intro Sort, using integer arithmetic to test for deviation from logarithmic complexity:
for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; ) {
pair<_RanIt, _RanIt> _Mid = _Unguarded_partition(_First, _Last);
_Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions
if (_Mid.first - _First < _Last - _Mid.second) {
_Sort(_First, _Mid.first, _Ideal);
_First = _Mid.second;
} else {
_Sort(_Mid.second, _Last, _Ideal);
_Last = _Mid.first;
}
}
⑨
#include "cute.h"
#include "ide_listener.h"
#include "cute_runner.h"
void thisIsATest() {
ASSERTM("start writing tests", false);
}
⑩
This implements a complete reference-counted object cache and leverages at least five different C++11 features or conveniences – thread-safe initialization of function local statics, std::mutex, std::shared_ptr, std::weak_ptr thread-safe .lock, and std::map auto-insertion – only that last one was available in C++98, all the rest are new in C++11.
shared_ptr<widget> get_widget( int id ) {
static map<int, weak_ptr<widget>> cache;
static mutex mut_cache;
lock_guard<mutex> hold( mut_cache );
auto sp = cache[id].lock();
if( !sp ) cache[id] = sp = load_widget( id );
return sp;
}
⑪
A declaration of the distance algorithm using Concepts Lite (including features not yet proposed). Assume that Signed and Input_iterator are previously defined concepts:
template<typename I>
concept bool In = Input_iterator<I>;
// Distance algorithm
Signed distance(In first, In last);
⑫
This is part of an implementation of a switch-case-like construct that can switch on anything that’s comparable with operator==, using variadic templates and lambdas. The bit shown does the recursive walking of cases, carrying the value to switch, the case value, and the case body into the recursion terminator function. The terminator simply invokes the case-body lambda (or any function object type, for that matter) if the comparison is true.
template <class X, class T, class U>
void super_case_impl(X val, T val2, U y)
{
if (val == val2) {
y();
}
}
template <class X, class T, class U, class ...Pairs>
void super_case_impl(X val, T val2, U func, Pairs... case_pairs) {
super_case_impl(val, val2, func);
super_case_impl(val, case_pairs...);
}
⑬
Nested classes are cool for hiding implementation details.
List:
class List
{
public:
List(): head(NULL), tail(NULL) {}
private:
class Node
{
public:
int data;
Node* next;
Node* prev;
};
private:
Node* head;
Node* tail;
};
Here I don’t want to expose Node as other people may decide to use the class and that would hinder me from updating my class as anything exposed is part of the public API and must be maintained forever. By making the class private, I not only hide the implementation I am also saying this is mine and I may change it at any time so you can not use it.
Look at std::list or std::map they all contain hidden classes (or do they?). The point is they may or may not, but because the implementation is private and hidden the builders of the STL were able to update the code without affecting how you used the code, or leaving a lot of old baggage laying around the STL because they need to maintain backwards compatibility with some fool who decided they wanted to use the Node class that was hidden inside <list>.