C++ Library Extensions 2022.12.09
To help learn modern C++ programming
exception_safe.cpp
Go to the documentation of this file.
1#include <iostream>
2#include <vector>
3#include <memory>
4#include <type_traits>
5
6namespace permu
7{
8
9 auto nl = "\n";
10
11 auto& cout = std::cout;
12
13 template<typename ElementType>
14 using set_t = std::vector<ElementType>; // container for set elements
15
16 template<typename ElementType>
17 using set_of_sets_t = set_t<set_t<ElementType>>; // container for permutations
18
19
20 template<typename ElementType>
23 {
24 if(L.empty())
25 {
26 permutations.emplace_back(R);
27 }
28 else
29 {
30 size_t size = L.size();
31
32 // make a room for last element
33 R.emplace_back(ElementType{});
34
35 /*
36 if an exception is thrown
37 before R.pop_back() is reached
38 this program does not work properly
39
40 we need to handle this issue
41 in EXCEPTION-SAFE manner
42 */
43
44 auto CreateCleanup = [] (auto& obj)
45 {
46 struct CleanUpPlease
47 {
48 using obj_t = std::remove_reference_t<decltype(obj)>;
49
50 obj_t& m_obj;
51
52 CleanUpPlease(obj_t& o): m_obj{o} { }
53
54 ~CleanUpPlease()
55 {
56 // cout <<"Wow... popping back! " << nl;
57 m_obj.pop_back();
58 }
59
60 };
61
62 return CleanUpPlease{ obj };
63 };
64
65 // clean_block is a local instance of struct CleanUpPlease
66 // auto clean_block = CreateCleanup(R);
67
68
69 auto r_pop_back = [&R](auto ptr)
70 {
71 cout <<"Wow, popping again "<< nl;
72 R.pop_back();
73 };
74
75 using r_type_t = std::remove_reference_t<decltype(R)>;
76
77 // clean_up is also a local variable
78 std::unique_ptr<r_type_t, decltype(r_pop_back)>
79 clean_up(&R, r_pop_back);
80
81 for(size_t i_th = 0; i_th < size; ++i_th)
82 {
83 // copy L to copied_L
84 auto copied_L = L;
85
86 // remove i_th element from copied_L
87 copied_L.erase(copied_L.begin()+i_th);
88
89 // move i_th element from L to R
90 // R.emplace_back( L[i_th] );
91 R.back() = L[i_th];
92
93 enum_permu(permutations,copied_L, R);
94
95 // R.pop_back();
96 }
97
98 // ONE STAGE is done
99 // R.pop_back();
100 }
101 }
102
103 template<typename ElementType>
105 {
106 set_of_sets_t<ElementType> permutations;
107
108 set_t<ElementType> L {0, 1, 2, 3, 4};
109
110 set_t<ElementType> R; R.reserve(L.size());
111
112 enum_permu(permutations, L, R);
113
114 for(size_t i = 0; i < permutations.size(); ++i)
115 {
116 for(size_t j= 0; j < permutations[i].size(); ++j)
117 {
118 cout << permutations[i][j] <<", ";
119 }
120
121 cout << nl;
122 }
123
124 cout << nl;
125 }
126}
127
128int main()
129{
130 permu::test_enum_permutations<int>();
131}
132
133
auto & cout
int main()
set_t< set_t< ElementType > > set_of_sets_t
std::vector< ElementType > set_t
void test_enum_permutations()
void enum_permu(set_of_sets_t< ElementType > &permutations, const set_t< ElementType > &L, set_t< ElementType > &R)
auto & cout