Skip to content

Commit a26b463

Browse files
committed
Adding tests for fold expressions
1 parent 32655be commit a26b463

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

C++17/fold_expressions.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,71 @@
1+
/*
2+
* 4. FOLD EXPRESSIONS
3+
*
4+
* Fold expressions provide the tools to apply BINARY OPERATORS to all elements in a
5+
* parameter pack without having of recursive template unpacking or intitializer tricks
6+
*
7+
* There are 4 forms of a fold expression:
8+
* (... OP pack) // Unary right fold => ((arg1 [+] arg2) [+] ...)
9+
* (pack OP ...) // Unary left fold => (... [+] (arg2 [+] arg3))
10+
* (init OP ... OP pack) // Binary left fold => ((init [+] arg1) [+] arg2) [+] ...)
11+
* (pack OP ... OP init) // Binary right fold => (... [+] (arg2 [+] (arg3 [+] init)))
12+
*/
113
#include <iostream>
214
#include <vector>
315
#include <set>
416
#include <string>
5-
//#include <print> // Needs to be included if we are using C++23 print function
17+
#include <cassert>
18+
#include <sstream>
619

7-
//size_t... I is a std::integer_sequence whose values are specified by a non-type template
20+
//(size_t... I) is a std::integer_sequence whose values are specified by a non-type template
821
template<typename TupleT, size_t... IdxT>
9-
void print(const TupleT& tupl, std::index_sequence<IdxT...>){
22+
std::string print(const TupleT& tupl, std::index_sequence<IdxT...>){
1023
//This experssion (..., operator) folds the tuple by applying operator to
1124
// each of its elements going from left to right
12-
std::cout << "(";
13-
(..., (std::cout << (IdxT == 0 ? "" : ", ") << std::get<IdxT>(tupl)));
14-
std::cout << ")\n";
25+
std::ostringstream oss;
26+
oss << "(";
27+
(..., (oss << (IdxT == 0 ? "" : ", ") << std::get<IdxT>(tupl)));
28+
oss << ")\n";
29+
return oss.str();
1530
}
1631

1732
// This is a non-type template that takes a tuple with multiple arguments of some type T
1833
template<typename... T>
19-
void printTuple(const std::tuple<T...>& tupl){
20-
//std::make_integer_sequence creates a sequence of integers of size equal to the number of arguments of T
21-
print(tupl, std::make_index_sequence<sizeof...(T)>());
34+
std::string printTuple(const std::tuple<T...>& tupl){
35+
// std::make_integer_sequence creates a sequence of integers of size equal to the number of arguments of T
36+
return print(tupl, std::make_index_sequence<sizeof...(T)>());
2237
}
2338

2439
int main(){
25-
std::vector<std::tuple<std::string>> my_list = {("5","3","1"),("1","3","2"),("3","5","A"),("6","4","5")};
40+
std::cout << "===== Test : Fold expressions applied to tuple printing =====\n";
2641

27-
auto a = std::make_index_sequence<4>();
28-
for(auto tupl_ : my_list){
29-
//std::cout << std::fmt("{}", my_list[i]) << std::endl; //For C++20 use format
30-
//print("{}", my_list[i]); // For C++23 use print
31-
printTuple(tupl_);
42+
std::vector<std::tuple<std::string, std::string, std::string>> my_list = {
43+
{"5","3","1"},
44+
{"1","3","2"},
45+
{"3","5","A"},
46+
{"6","4","5"}
47+
};
48+
49+
std::vector<std::string> expected_output = {"(5, 3, 1)\n",
50+
"(1, 3, 2)\n",
51+
"(3, 5, A)\n",
52+
"(6, 4, 5)\n"};
53+
for(size_t i = 0; i < my_list.size(); i++)
54+
{
55+
const auto& tupl_ = my_list[i];
56+
std::string result = printTuple(tupl_);
57+
if (result != expected_output[i])
58+
{
59+
std::cerr << "Failed on tuple " << i << ": got " << result
60+
<< " expected " << expected_output[i] << "\n";
61+
assert(false);
62+
}
63+
// In C++20 use std::fmt as follows:
64+
// std::cout << std::fmt("{}", my_list[i]) << std::endl;
65+
// In C++23 use std::print
66+
// print("{}", my_list[i]);
3267
}
68+
std::cout << "All tuples verified successfully\n";
3369
return 0;
3470
}
71+

0 commit comments

Comments
 (0)