1 /*******************************************************************************
2  * tests/meta/function_stack_test.cpp
3  *
4  * Part of tlx - http://panthema.net/tlx
5  *
6  * Copyright (C) 2015 Sebastian Lamm <seba.lamm@gmail.com>
7  * Copyright (C) 2015-2017 Timo Bingmann <tb@panthema.net>
8  *
9  * All rights reserved. Published under the Boost Software License, Version 1.0
10  ******************************************************************************/
11 
12 #include <tlx/meta/function_stack.hpp>
13 
14 #include <tlx/die.hpp>
15 
16 #include <iostream>
17 #include <string>
18 #include <vector>
19 
test_stack1()20 static void test_stack1() {
21 
22     std::vector<double> elements;
23 
24     // User-defined functions
25     auto fmap_fn =
26         [=](double input, auto emit_func) {
27             emit_func(input);
28             emit_func(input);
29         };
30 
31     auto map_fn =
32         [=](double input) {
33             return 2 * input;
34         };
35 
36     auto filter_fn =
37         [=](double input) {
38             return input > 80;
39         };
40 
41     double total = 0;
42 
43     auto save_fn =
44         [&total](double input) {
45             // elements.push_back(input);
46             total += input;
47         };
48 
49     // Converted emitter functions
50     auto conv_map_fn =
51         [=](double input, auto emit_func) {
52             emit_func(map_fn(input));
53         };
54 
55     auto conv_filter_fn =
56         [=](double input, auto emit_func) {
57             if (filter_fn(input)) emit_func(input);
58         };
59 
60     auto empty_stack = tlx::FunctionStack<double>();
61     static_assert(empty_stack.empty, "FunctionStack::empty is wrong");
62 
63     auto new_stack = tlx::make_function_stack<double>(fmap_fn);
64     static_assert(!new_stack.empty, "FunctionStack::empty is wrong");
65 
66     auto new_stack2 = new_stack.push(conv_map_fn);
67     auto new_stack3 = new_stack2.push(conv_filter_fn);
68     auto new_stack4 = new_stack3.push(save_fn);
69     auto composed_function = new_stack4.fold();
70 
71     for (size_t i = 0; i != 1000; ++i) {
72         composed_function(42);
73         composed_function(2);
74         composed_function(50);
75     }
76 
77     die_unequal(total, 368000u);
78 }
79 
test_simple_deduction_test()80 static void test_simple_deduction_test() {
81 
82     auto fmap_fn1 =
83         [=](int input, auto emit_func) {
84             emit_func(std::to_string(input));
85         };
86 
87     auto fmap_fn2 =
88         [=](const std::string& input, auto emit_func) {
89             emit_func(input + " Hello");
90             emit_func(10);
91         };
92 
93     auto new_stack1 = tlx::make_function_stack<int>(fmap_fn1);
94     auto new_stack2 = new_stack1.push(fmap_fn2);
95 
96     std::vector<std::string> output;
97 
98     auto save_output = [&](auto) {
99                            output.emplace_back("123");
100                        };
101 
102     auto new_stack3 = new_stack2.push(save_output);
103     new_stack3.fold()(42);
104 
105     die_unequal(output.size(), 2u);
106     die_unequal(output[0], "123");
107     die_unequal(output[1], "123");
108 }
109 
test_stack_maker()110 static void test_stack_maker() {
111 
112     std::vector<std::string> out;
113 
114     auto result =
115         tlx::FunctionStack<double>()
116         & ([](const int& d, auto emit) { emit(d + 1); })
117         & ([](const int& d, auto emit) { emit(std::to_string(2 * d)); })
118         & ([](const std::string& s, auto emit) { emit(s + "2"); })
119         & ([&](const std::string& s) { out.emplace_back(s); });
120 
121     auto x = result.fold();
122     x(5);
123     die_unequal(out.front(), "122");
124 }
125 
main()126 int main() {
127     test_stack1();
128     test_simple_deduction_test();
129     test_stack_maker();
130 
131     return 0;
132 }
133 
134 /******************************************************************************/
135