@@ -144,7 +144,81 @@ TEST(variadic_tuple_iteration, DISABLED_we_can_transform_an_indexed_tuple) {
144144 EXPECT_EQ (3 , std::get<1 >(result));
145145 EXPECT_NEAR (4.5 , std::get<2 >(result), .0001 );
146146}
147- auto product = [](auto ... functions)
147+
148+ using Amount = int ;
149+ struct Account {
150+ Amount balance;
151+ };
152+ auto consult (const Account &a) {
153+ return a.balance ;
154+ }
155+ auto transaction (Account& from, Account& to, Amount amount)
156+ {
157+ if (from.balance <= amount) return false ;
158+ from.balance -= amount;
159+ to.balance += amount;
160+ return true ;
161+ }
162+
163+
164+ // TODO:
165+ // uncomment next line
166+ // #define I_CAN_WRAP_FUNCTIONS
167+ //
168+ // And now...
169+ //
170+ // create the `writer` meta-function so that it
171+ // returns a function that
172+ // * accepts an existing M _and_ all the arguments for `f`
173+ // * appends `m` to an existing M
174+ // * returns the tuple { m, f(args) }
175+ //
176+ // GOAL:
177+ // Learn to work with functions as first class citizens
178+ // allows you to write more orthogonal code: the code
179+ // concerned with the logging does not need to have anything to
180+ // do with the code performing the action.
181+ //
182+ // HINT:
183+ // use generic lambdas
184+ // mind reference arguments! They need to be perfect-forwarded!
185+ //
186+ #ifdef I_CAN_WRAP_FUNCTIONS
187+ template <typename M, typename F>
188+ auto writer (M m, F f) {
189+ }
190+ #endif
191+
192+ TEST (variadic_templates, DISABLED_can_be_used_to_wrap_existing_functions) {
193+ Account mine{1000 };
194+ Account yours{50 };
195+
196+ ASSERT_TRUE (transaction (mine, yours, 50 ));
197+ ASSERT_EQ (950 , mine.balance );
198+ ASSERT_EQ (100 , yours.balance );
199+
200+ #ifdef I_CAN_WRAP_FUNCTIONS
201+ using namespace std ::string_literals;
202+ auto v_consult = writer (" consult\n " s, consult);
203+ auto v_transaction = writer (" transaction\n " s, transaction);
204+
205+ std::string logs0;
206+ {
207+ auto [logs1, balance] = v_consult (logs0, mine);
208+ EXPECT_EQ (" consult\n " , logs1);
209+ EXPECT_EQ (950 , balance);
210+ EXPECT_EQ (100 , yours.balance );
211+ auto [logs2, u] = v_transaction (logs1, yours, mine, 50 );
212+ EXPECT_EQ (" consult\n transaction\n " , logs2);
213+ EXPECT_EQ (true , u);
214+ EXPECT_EQ (1000 , mine.balance );
215+ EXPECT_EQ (50 , yours.balance );
216+ }
217+ #endif
218+ }
219+
220+
221+ auto tabulate = [](auto ... functions)
148222{
149223 return [](auto ...arguments ) {
150224 return std::string{ " not implemented" };
@@ -156,11 +230,11 @@ TEST(composition, DISABLED_print_a_matrix)
156230
157231 // this exercise will take some more time...
158232 //
159- // TODO: fill in the `product ` function so that it prints a table
233+ // TODO: fill in the `tabulate ` function so that it prints a table
160234 // of the functions applied to the arguments
161235 // GOAL: learn to deal with multiple packs and expansions
162236 // GRADE: HARD
163- const auto table = product (
237+ const auto table = tabulate (
164238 [](auto i) { return i; },
165239 [](auto i) { return i * i; },
166240 [](auto i) { return i * i*i - 1 ; }
@@ -172,7 +246,7 @@ TEST(composition, DISABLED_print_a_matrix)
172246
173247 EXPECT_EQ (R"( 1, 4, 9, 100
1742481, 8, 27, 1000)" ,
175- product ([](auto i) { return i*i; },
249+ tabulate ([](auto i) { return i*i; },
176250 [](auto i) { return i*i*i; })
177251 (1 , 2 , 3 , 10 ));
178252}
0 commit comments