C++17-compatible imitation of Java 8 Stream API. Elements are processed lazily and with minimum overhead.
#include <stream/stream.h> // stream::Stream
#include <stream/operations.h> // stream::ops::*
#include <vector> // std::vector
#include <string> // std::string
#include <algorithm> // std::transform
#include <iostream> // std::cout
int main()
{
namespace ops = stream::ops;
const std::vector strings = {
"dignity",
"respect",
"Fred's",
"sun",
"color",
"friends",
"premium",
"run",
"sector",
"fried",
"smile",
"Fritos",
"for",
"global",
"Fridays",
"broadcast",
"food"
};
// no copying or moving, strings are stored via reference
stream::Stream(strings)
| ops::filter([](const char *str) { // select only strings started with 'F' or 'f'
return (str[0] == 'f' || str[0] == 'F');
}) // nothing will be evaluated at this point
| ops::map([](std::string str) { // make every word is in uppercase
(void)std::transform(str.begin(), str.end(), str.begin(), [](unsigned char ch) { return std::toupper(ch); });
return str;
}) // still nothing will be evaluated
| ops::print_to(std::cout); // there is the terminal operation - causes evaluating everything
return 0;
}Output:
FRED'S FRIENDS FRIED FRITOS FOR FRIDAYS FOOD
-
Supported terminal operations:
print_to(ostream)- prints all elements of the stream to a given output streamostream;reduce(identityFn, accumulatorFn)- reduces all elements of the stream to 1 similar to the following pseudo-code:stream::Stream s(...); auto v = identityFn(s.getNext()); while (!s.isEnd()) v = accumulatorFn(v, s.getNext()); return v;
reduce(accumulatorFn)- reduces all elements of the stream to 1 similar to the following pseudo-code:stream::Stream s(...); auto v = s.getNext(); while (!s.isEnd()) v = accumulatorFn(v, s.getNext()); return v;
nth(n)- returnsnth element of the stream;to_vector()- moves all elements of the origin stream to astd::vector.
-
Supported non terminal operations:
skip(n)- skips n elements of the stream;get(n)- takes only n first elements from the stream;map(mapFn)- creates a new stream of results of applying the given functormapFnto every element of the given stream;filter(predicateFn)- leaves only elements to which applyingpredicateFnfunctor returns true;group(n)- creates a new stream ofstd::vectors withnelements of the origin stream.
- Using the library:
- C++17-compatible compiler and STL. Tested with:
GCC 7.5,GCC 8.4,GCC 9.3;Clang 8,Clang 9;MSVC 19.16.27041.0 (MSVS 2017),MSVC 19.26.28806.0 (MSVS 2019).
- C++17-compatible compiler and STL. Tested with:
- For running tests, you need:
See Requirements chapter first.
Just use CMake (run from project root):
# Build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
# Running tests
ctest -C Release -VNote: This project uses GoogleTest for testing.
See Requirements chapter first.
CMake scripts provides the next additional variables for setting up the measurement:
COLLECT_CODE_COVERAGE=<LCOV|OTHER|OFF>- if set toLCOVthen code coverage targetcollect_coveragewill be created.OTHERassumes compiling/linking code for measuring via different than lcov instrument (gcov for example).OFFdoes nothing and set by default.GCOV_PATH- allows to specify path to gcov executable.gcovby default.
It's recommended to build the code in Debug mode for coverage measurement.
Example (run from project root):
# Build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=gcc-6.3.0 \
-DCMAKE_CXX_COMPILER=g++-6.3.0 \
-DCOLLECT_CODE_COVERAGE=LCOV \
-DGCOV_PATH=gcov-6.3.0 \
..
# Collecting the coverage:
cmake --build . --target collect_coverage
# Html reports will be generated. Use browser to see it:
<your_browser_name> ./collect_coverage/index.html &