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)
- returnsn
th 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 functormapFn
to every element of the given stream;filter(predicateFn)
- leaves only elements to which applyingpredicateFn
functor returns true;group(n)
- creates a new stream ofstd::vector
s withn
elements 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 -V
Note: 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 toLCOV
then code coverage targetcollect_coverage
will be created.OTHER
assumes compiling/linking code for measuring via different than lcov instrument (gcov for example).OFF
does nothing and set by default.GCOV_PATH
- allows to specify path to gcov executable.gcov
by 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 &