Skip to content

Latest commit

 

History

History
83 lines (73 loc) · 3.16 KB

Readme.md

File metadata and controls

83 lines (73 loc) · 3.16 KB

Build Status GitHub license Coverage Status

Streams++

Streams++ is a C++14 library inspired by Rust-lang Iterator trait and Java 8 Streams API. A stream represents a sequence of elements that come from some source. The stream itselt and most operations upon its elements are lazy, so nothing is evaluated until it has to be done. This allows to perform computation in a functional style by chaining operations stream supports.

Installation

Streams++ is a header only library, so just include Streams.h. It has no external dependencies, but uses std::optional<T> type from <experimental/optional>.

If you are using Visual C++ it's almost sure there is no <experimental/optional> header. In that case the library relies on akrzemi1/Optional library. You'll need extra steps after pulling this repository:

git submodule init
git submodule update

You can use cmake to build tests and examples alltogeather.

Examples

Creating a stream from a collection

std::vector<int> vec {/*...*/};
auto stream = streams::from(vec);

Sum of squares of multiples of 17

int sum = streams::from(vec) // you can use a 'stream' created before
    .filter([](auto& e) {return e % 17 == 0; })
    .map([](auto& e) { return e*e; })
    .fold(0, std::plus<>{});

First 5 roman numbers with more than 10 'digits'

std::string to_roman(size_t i);

streams::generate::counter(1)
    .map(to_roman)
    .enumerate()
    .filter([](auto& e) {return e.v.length() > 10; })
    .take(5)
    .forEach([](auto& e) { std::cout << e.i + 1 << " == " << e.v << std::endl; });

enumerate() will stream struct with index and value members. In case you want to use idiomatic std::tuple call enumerateTup() here.

If you are curious the result is:

388 == CCCLXXXVIII
788 == DCCLXXXVIII
838 == DCCCXXXVIII
878 == DCCCLXXVIII
883 == DCCCLXXXIII

Under the hood

Streams are designed to be fast and lightweight proxy objects. Every stream is a different class with statically dispatched methods. More than that, a stream

  • doesn't own the underlying collection;
  • doesn't modify the underlying collection;
  • doesn't allocate memory on the heap;
  • never throws exceptions unless it's thrown from inside user code;
  • is valid to copy, though the state will also be copied.

As a proxy object, stream should never outlive its source.

Stream is a single-use object. It can't be reset or used again after its source is depleted. Actually, using an exhausted stream is a valid operation, but the stream will remain empty forever.

Tests

You'll need googletest. Simply run

$ mkdir build
$ cd build
$ cmake ..
$ make
$ ctest -VV

or use generated project file on Windows.