2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef FOLLY_GEN_BASE_H_
18 #error This file may only be included from folly/gen/Base.h
21 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wshadow"
25 namespace folly { namespace gen {
28 * ArgumentReference - For determining ideal argument type to receive a value.
31 struct ArgumentReference
32 : public std::conditional<
33 std::is_reference<T>::value,
34 T, // T& -> T&, T&& -> T&&, const T& -> const T&
35 typename std::conditional<std::is_const<T>::value,
36 T&, // const int -> const int&
41 * Group - The output objects from the GroupBy operator
43 template <class Key, class Value>
44 class Group : public GenImpl<Value&&, Group<Key, Value>> {
46 static_assert(!std::is_reference<Key>::value &&
47 !std::is_reference<Value>::value,
48 "Key and Value must be decayed types");
50 typedef std::vector<Value> VectorType;
52 typedef Value ValueType;
54 Group(Key key, VectorType values)
55 : key_(std::move(key)), values_(std::move(values)) {}
57 const Key& key() const { return key_; }
59 size_t size() const { return values_.size(); }
60 const VectorType& values() const { return values_; }
61 VectorType& values() { return values_; }
63 VectorType operator|(const detail::Collect<VectorType>&) const {
67 VectorType operator|(const detail::CollectTemplate<std::vector>&) const {
72 void foreach(Body&& body) const {
73 for (auto& value : values_) {
74 body(std::move(value));
78 template <class Handler>
79 bool apply(Handler&& handler) const {
80 for (auto& value : values_) {
81 if (!handler(std::move(value))) {
88 // GroupBy only takes in finite generators, so we only have finite groups
89 static constexpr bool infinite = false;
93 mutable VectorType values_;
98 // Classes used for the implementation of Sources, Operators, and Sinks
101 ******************************* Sources ***************************************
105 * ReferencedSource - Generate values from an STL-like container using
106 * iterators from .begin() until .end(). Value type defaults to the type of
107 * *container->begin(). For std::vector<int>, this would be int&. Note that the
108 * value here is a reference, so the values in the vector will be passed by
109 * reference to downstream operators.
111 * This type is primarily used through the 'from' helper method, like:
113 * string& longestName = from(names)
114 * | maxBy([](string& s) { return s.size() });
116 template <class Container, class Value>
117 class ReferencedSource
118 : public GenImpl<Value, ReferencedSource<Container, Value>> {
119 Container* container_;
122 explicit ReferencedSource(Container* container) : container_(container) {}
124 template <class Body>
125 void foreach(Body&& body) const {
126 for (auto& value : *container_) {
127 body(std::forward<Value>(value));
131 template <class Handler>
132 bool apply(Handler&& handler) const {
133 for (auto& value : *container_) {
134 if (!handler(std::forward<Value>(value))) {
141 // from takes in a normal stl structure, which are all finite
142 static constexpr bool infinite = false;
146 * CopiedSource - For producing values from eagerly from a sequence of values
147 * whose storage is owned by this class. Useful for preparing a generator for
148 * use after a source collection will no longer be available, or for when the
149 * values are specified literally with an initializer list.
151 * This type is primarily used through the 'fromCopy' function, like:
153 * auto sourceCopy = fromCopy(makeAVector());
154 * auto sum = sourceCopy | sum;
155 * auto max = sourceCopy | max;
157 * Though it is also used for the initializer_list specialization of from().
159 template <class StorageType, class Container>
161 : public GenImpl<const StorageType&, CopiedSource<StorageType, Container>> {
162 static_assert(!std::is_reference<StorageType>::value,
163 "StorageType must be decayed");
166 // Generator objects are often copied during normal construction as they are
167 // encapsulated by downstream generators. It would be bad if this caused
168 // a copy of the entire container each time, and since we're only exposing a
169 // const reference to the value, it's safe to share it between multiple
171 static_assert(!std::is_reference<Container>::value,
172 "Can't copy into a reference");
173 std::shared_ptr<const Container> copy_;
176 typedef Container ContainerType;
178 template <class SourceContainer>
179 explicit CopiedSource(const SourceContainer& container)
180 : copy_(new Container(begin(container), end(container))) {}
182 explicit CopiedSource(Container&& container)
183 : copy_(new Container(std::move(container))) {}
185 // To enable re-use of cached results.
186 CopiedSource(const CopiedSource<StorageType, Container>& source)
187 : copy_(source.copy_) {}
189 template <class Body>
190 void foreach(Body&& body) const {
191 for (const auto& value : *copy_) {
196 template <class Handler>
197 bool apply(Handler&& handler) const {
198 // The collection may be reused by others, we can't allow it to be changed.
199 for (const auto& value : *copy_) {
200 if (!handler(value)) {
207 // from takes in a normal stl structure, which are all finite
208 static constexpr bool infinite = false;
212 * RangeSource - For producing values from a folly::Range. Useful for referring
213 * to a slice of some container.
215 * This type is primarily used through the 'from' function, like:
217 * auto rangeSource = from(folly::range(v.begin(), v.end()));
218 * auto sum = rangeSource | sum;
220 * Reminder: Be careful not to invalidate iterators when using ranges like this.
222 template <class Iterator>
223 class RangeSource : public GenImpl<typename Range<Iterator>::reference,
224 RangeSource<Iterator>> {
225 Range<Iterator> range_;
228 RangeSource() = default;
229 explicit RangeSource(Range<Iterator> range) : range_(std::move(range)) {}
231 template <class Handler>
232 bool apply(Handler&& handler) const {
233 for (auto& value : range_) {
234 if (!handler(value)) {
241 template <class Body>
242 void foreach(Body&& body) const {
243 for (auto& value : range_) {
248 // folly::Range only supports finite ranges
249 static constexpr bool infinite = false;
253 * Sequence - For generating values from beginning value, incremented along the
254 * way with the ++ and += operators. Iteration may continue indefinitely.
255 * Value type specified explicitly.
257 * This type is primarily used through the 'seq' and 'range' function, like:
259 * int total = seq(1, 10) | sum;
260 * auto indexes = range(0, 10);
261 * auto endless = seq(0); // 0, 1, 2, 3, ...
263 template <class Value, class SequenceImpl>
264 class Sequence : public GenImpl<const Value&, Sequence<Value, SequenceImpl>> {
265 static_assert(!std::is_reference<Value>::value &&
266 !std::is_const<Value>::value,
267 "Value mustn't be const or ref.");
272 explicit Sequence(Value start, SequenceImpl impl)
273 : start_(std::move(start)), impl_(std::move(impl)) {}
275 template <class Handler>
276 bool apply(Handler&& handler) const {
277 for (Value current = start_; impl_.test(current); impl_.step(current)) {
278 if (!handler(current)) {
285 template <class Body>
286 void foreach(Body&& body) const {
287 for (Value current = start_; impl_.test(current); impl_.step(current)) {
292 // Let the implementation say if we are infinite or not
293 static constexpr bool infinite = SequenceImpl::infinite;
297 * Sequence implementations (range, sequence, infinite, with/without step)
299 template <class Value>
304 explicit RangeImpl(Value end) : end_(std::move(end)) {}
305 bool test(const Value& current) const { return current < end_; }
306 void step(Value& current) const { ++current; }
307 static constexpr bool infinite = false;
310 template <class Value, class Distance>
311 class RangeWithStepImpl {
316 explicit RangeWithStepImpl(Value end, Distance step)
317 : end_(std::move(end)), step_(std::move(step)) {}
318 bool test(const Value& current) const { return current < end_; }
319 void step(Value& current) const { current += step_; }
320 static constexpr bool infinite = false;
323 template <class Value>
328 explicit SeqImpl(Value end) : end_(std::move(end)) {}
329 bool test(const Value& current) const { return current <= end_; }
330 void step(Value& current) const { ++current; }
331 static constexpr bool infinite = false;
334 template <class Value, class Distance>
335 class SeqWithStepImpl {
340 explicit SeqWithStepImpl(Value end, Distance step)
341 : end_(std::move(end)), step_(std::move(step)) {}
342 bool test(const Value& current) const { return current <= end_; }
343 void step(Value& current) const { current += step_; }
344 static constexpr bool infinite = false;
347 template <class Value>
350 bool test(const Value& /* current */) const { return true; }
351 void step(Value& current) const { ++current; }
352 static constexpr bool infinite = true;
356 * GenratorBuilder - Helper for GENERTATOR macro.
358 template <class Value>
359 struct GeneratorBuilder {
360 template <class Source,
361 class Yield = detail::Yield<Value, Source>>
362 Yield operator+(Source&& source) {
363 return Yield(std::forward<Source>(source));
368 * Yield - For producing values from a user-defined generator by way of a
371 template <class Value, class Source>
372 class Yield : public GenImpl<Value, Yield<Value, Source>> {
376 explicit Yield(Source source) : source_(std::move(source)) {}
378 template <class Handler>
379 bool apply(Handler&& handler) const {
381 auto body = [&](Value value) {
382 if (!handler(std::forward<Value>(value))) {
394 template <class Body>
395 void foreach(Body&& body) const {
396 source_(std::forward<Body>(body));
400 template <class Value>
401 class Empty : public GenImpl<Value, Empty<Value>> {
403 template <class Handler>
404 bool apply(Handler&&) const {
408 template <class Body>
409 void foreach(Body&&) const {}
411 // No values, so finite
412 static constexpr bool infinite = false;
415 template <class Value>
416 class SingleReference : public GenImpl<Value&, SingleReference<Value>> {
417 static_assert(!std::is_reference<Value>::value,
418 "SingleReference requires non-ref types");
422 explicit SingleReference(Value& ref) : ptr_(&ref) {}
424 template <class Handler>
425 bool apply(Handler&& handler) const {
426 return handler(*ptr_);
429 template <class Body>
430 void foreach(Body&& body) const {
434 // One value, so finite
435 static constexpr bool infinite = false;
438 template <class Value>
439 class SingleCopy : public GenImpl<const Value&, SingleCopy<Value>> {
440 static_assert(!std::is_reference<Value>::value,
441 "SingleCopy requires non-ref types");
445 explicit SingleCopy(Value value) : value_(std::forward<Value>(value)) {}
447 template <class Handler>
448 bool apply(Handler&& handler) const {
449 return handler(value_);
452 template <class Body>
453 void foreach(Body&& body) const {
457 // One value, so finite
458 static constexpr bool infinite = false;
462 ***************************** Operators ***************************************
466 * Map - For producing a sequence of values by passing each value from a source
467 * collection through a predicate.
469 * This type is usually used through the 'map' or 'mapped' helper function:
471 * auto squares = seq(1, 10) | map(square) | asVector;
473 template <class Predicate>
474 class Map : public Operator<Map<Predicate>> {
480 explicit Map(Predicate pred) : pred_(std::move(pred)) {}
482 template <class Value,
484 class Result = typename ArgumentReference<
485 typename std::result_of<Predicate(Value)>::type>::type>
486 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
491 explicit Generator(Source source, const Predicate& pred)
492 : source_(std::move(source)), pred_(pred) {}
494 template <class Body>
495 void foreach(Body&& body) const {
497 [&](Value value) { body(pred_(std::forward<Value>(value))); });
500 template <class Handler>
501 bool apply(Handler&& handler) const {
502 return source_.apply([&](Value value) {
503 return handler(pred_(std::forward<Value>(value)));
507 static constexpr bool infinite = Source::infinite;
510 template <class Source,
512 class Gen = Generator<Value, Source>>
513 Gen compose(GenImpl<Value, Source>&& source) const {
514 return Gen(std::move(source.self()), pred_);
517 template <class Source,
519 class Gen = Generator<Value, Source>>
520 Gen compose(const GenImpl<Value, Source>& source) const {
521 return Gen(source.self(), pred_);
526 * Filter - For filtering values from a source sequence by a predicate.
528 * This type is usually used through the 'filter' helper function, like:
530 * auto nonEmpty = from(strings)
531 * | filter([](const string& str) -> bool {
532 * return !str.empty();
535 * Note that if no predicate is provided, the values are casted to bool and
536 * filtered based on that. So if pointers is a vector of pointers,
538 * auto nonNull = from(pointers) | filter();
540 * will give a vector of all the pointers != nullptr.
542 template <class Predicate>
543 class Filter : public Operator<Filter<Predicate>> {
548 explicit Filter(Predicate pred) : pred_(std::move(pred)) {}
550 template <class Value, class Source>
551 class Generator : public GenImpl<Value, Generator<Value, Source>> {
556 explicit Generator(Source source, const Predicate& pred)
557 : source_(std::move(source)), pred_(pred) {}
559 template <class Body>
560 void foreach(Body&& body) const {
561 source_.foreach([&](Value value) {
562 // NB: Argument not forwarded to avoid accidental move-construction
564 body(std::forward<Value>(value));
569 template <class Handler>
570 bool apply(Handler&& handler) const {
571 return source_.apply([&](Value value) -> bool {
572 // NB: Argument not forwarded to avoid accidental move-construction
574 return handler(std::forward<Value>(value));
580 static constexpr bool infinite = Source::infinite;
583 template <class Source,
585 class Gen = Generator<Value, Source>>
586 Gen compose(GenImpl<Value, Source>&& source) const {
587 return Gen(std::move(source.self()), pred_);
590 template <class Source,
592 class Gen = Generator<Value, Source>>
593 Gen compose(const GenImpl<Value, Source>& source) const {
594 return Gen(source.self(), pred_);
599 * Until - For producing values from a source until a predicate is satisfied.
601 * This type is usually used through the 'until' helper function, like:
603 * auto best = from(sortedItems)
604 * | until([](Item& item) { return item.score > 100; })
607 template <class Predicate>
608 class Until : public Operator<Until<Predicate>> {
613 explicit Until(Predicate pred) : pred_(std::move(pred)) {}
615 template <class Value, class Source>
616 class Generator : public GenImpl<Value, Generator<Value, Source>> {
621 explicit Generator(Source source, const Predicate& pred)
622 : source_(std::move(source)), pred_(pred) {}
624 template <class Handler>
625 bool apply(Handler&& handler) const {
626 bool cancelled = false;
627 source_.apply([&](Value value) -> bool {
628 if (pred_(value)) { // un-forwarded to disable move
631 if (!handler(std::forward<Value>(value))) {
640 // Theoretically an 'until' might stop an infinite
641 static constexpr bool infinite = false;
644 template <class Source,
646 class Gen = Generator<Value, Source>>
647 Gen compose(GenImpl<Value, Source>&& source) const {
648 return Gen(std::move(source.self()), pred_);
651 template <class Source,
653 class Gen = Generator<Value, Source>>
654 Gen compose(const GenImpl<Value, Source>& source) const {
655 return Gen(source.self(), pred_);
660 * Take - For producing up to N values from a source.
662 * This type is usually used through the 'take' helper function, like:
664 * auto best = from(docs)
665 * | orderByDescending(scoreDoc)
668 class Take : public Operator<Take> {
672 explicit Take(size_t count) : count_(count) {}
674 template <class Value, class Source>
675 class Generator : public GenImpl<Value, Generator<Value, Source>> {
680 explicit Generator(Source source, size_t count)
681 : source_(std::move(source)), count_(count) {}
683 template <class Handler>
684 bool apply(Handler&& handler) const {
689 bool cancelled = false;
690 source_.apply([&](Value value) -> bool {
691 if (!handler(std::forward<Value>(value))) {
700 // take will stop an infinite generator
701 static constexpr bool infinite = false;
704 template <class Source,
706 class Gen = Generator<Value, Source>>
707 Gen compose(GenImpl<Value, Source>&& source) const {
708 return Gen(std::move(source.self()), count_);
711 template <class Source,
713 class Gen = Generator<Value, Source>>
714 Gen compose(const GenImpl<Value, Source>& source) const {
715 return Gen(source.self(), count_);
720 * Stride - For producing every Nth value from a source.
722 * This type is usually used through the 'stride' helper function, like:
724 * auto half = from(samples)
727 class Stride : public Operator<Stride> {
731 explicit Stride(size_t stride) : stride_(stride) {
733 throw std::invalid_argument("stride must not be 0");
737 template <class Value, class Source>
738 class Generator : public GenImpl<Value, Generator<Value, Source>> {
743 explicit Generator(Source source, size_t stride)
744 : source_(std::move(source)), stride_(stride) {}
746 template <class Handler>
747 bool apply(Handler&& handler) const {
748 size_t distance = stride_;
749 return source_.apply([&](Value value) -> bool {
750 if (++distance >= stride_) {
751 if (!handler(std::forward<Value>(value))) {
760 template <class Body>
761 void foreach(Body&& body) const {
762 size_t distance = stride_;
763 source_.foreach([&](Value value) {
764 if (++distance >= stride_) {
765 body(std::forward<Value>(value));
771 // Taking every Nth of an infinite list is still infinte
772 static constexpr bool infinite = Source::infinite;
775 template <class Source,
777 class Gen = Generator<Value, Source>>
778 Gen compose(GenImpl<Value, Source>&& source) const {
779 return Gen(std::move(source.self()), stride_);
782 template <class Source,
784 class Gen = Generator<Value, Source>>
785 Gen compose(const GenImpl<Value, Source>& source) const {
786 return Gen(source.self(), stride_);
791 * Sample - For taking a random sample of N elements from a sequence
792 * (without replacement).
794 template <class Random>
795 class Sample : public Operator<Sample<Random>> {
800 explicit Sample(size_t count, Random rng)
801 : count_(count), rng_(std::move(rng)) {}
803 template <class Value,
806 class StorageType = typename std::decay<Value>::type>
808 : public GenImpl<StorageType&&,
809 Generator<Value, Source, Rand, StorageType>> {
810 static_assert(!Source::infinite, "Cannot sample infinite source!");
811 // It's too easy to bite ourselves if random generator is only 16-bit
812 static_assert(Random::max() >= std::numeric_limits<int32_t>::max() - 1,
813 "Random number generator must support big values");
819 explicit Generator(Source source, size_t count, Random rng)
820 : source_(std::move(source)), count_(count), rng_(std::move(rng)) {}
822 template <class Handler>
823 bool apply(Handler&& handler) const {
827 std::vector<StorageType> v;
829 // use reservoir sampling to give each source value an equal chance
830 // of appearing in our output.
832 source_.foreach([&](Value value) -> void {
833 if (v.size() < count_) {
834 v.push_back(std::forward<Value>(value));
836 // alternatively, we could create a std::uniform_int_distribution
837 // instead of using modulus, but benchmarks show this has
838 // substantial overhead.
839 size_t index = rng_() % n;
840 if (index < v.size()) {
841 v[index] = std::forward<Value>(value);
847 // output is unsorted!
848 for (auto& val : v) {
849 if (!handler(std::move(val))) {
856 // Only takes N elements, so finite
857 static constexpr bool infinite = false;
860 template <class Source,
862 class Gen = Generator<Value, Source, Random>>
863 Gen compose(GenImpl<Value, Source>&& source) const {
864 return Gen(std::move(source.self()), count_, rng_);
867 template <class Source,
869 class Gen = Generator<Value, Source, Random>>
870 Gen compose(const GenImpl<Value, Source>& source) const {
871 return Gen(source.self(), count_, rng_);
876 * Skip - For skipping N items from the beginning of a source generator.
878 * This type is usually used through the 'skip' helper function, like:
880 * auto page = from(results)
881 * | skip(pageSize * startPage)
884 class Skip : public Operator<Skip> {
888 explicit Skip(size_t count) : count_(count) {}
890 template <class Value, class Source>
891 class Generator : public GenImpl<Value, Generator<Value, Source>> {
896 explicit Generator(Source source, size_t count)
897 : source_(std::move(source)), count_(count) {}
899 template <class Body>
900 void foreach(Body&& body) const {
902 source_.foreach(body);
906 source_.foreach([&](Value value) {
910 body(std::forward<Value>(value));
915 template <class Handler>
916 bool apply(Handler&& handler) const {
918 return source_.apply(std::forward<Handler>(handler));
921 return source_.apply([&](Value value) -> bool {
926 return handler(std::forward<Value>(value));
930 // Skipping N items of an infinite source is still infinite
931 static constexpr bool infinite = Source::infinite;
934 template <class Source,
936 class Gen = Generator<Value, Source>>
937 Gen compose(GenImpl<Value, Source>&& source) const {
938 return Gen(std::move(source.self()), count_);
941 template <class Source,
943 class Gen = Generator<Value, Source>>
944 Gen compose(const GenImpl<Value, Source>& source) const {
945 return Gen(source.self(), count_);
950 * Order - For ordering a sequence of values from a source by key.
951 * The key is extracted by the given selector functor, and this key is then
952 * compared using the specified comparator.
954 * This type is usually used through the 'order' helper function, like:
956 * auto closest = from(places)
957 * | orderBy([](Place& p) {
958 * return -distance(p.location, here);
962 template <class Selector, class Comparer>
963 class Order : public Operator<Order<Selector, Comparer>> {
970 explicit Order(Selector selector) : selector_(std::move(selector)) {}
972 Order(Selector selector, Comparer comparer)
973 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
975 template <class Value,
977 class StorageType = typename std::decay<Value>::type,
978 class Result = typename std::result_of<Selector(Value)>::type>
980 : public GenImpl<StorageType&&,
981 Generator<Value, Source, StorageType, Result>> {
982 static_assert(!Source::infinite, "Cannot sort infinite source!");
987 typedef std::vector<StorageType> VectorType;
989 VectorType asVector() const {
990 auto comparer = [&](const StorageType& a, const StorageType& b) {
991 return comparer_(selector_(a), selector_(b));
993 auto vals = source_ | as<VectorType>();
994 std::sort(vals.begin(), vals.end(), comparer);
995 return std::move(vals);
999 Generator(Source source, Selector selector, Comparer comparer)
1000 : source_(std::move(source)),
1001 selector_(std::move(selector)),
1002 comparer_(std::move(comparer)) {}
1004 VectorType operator|(const Collect<VectorType>&) const {
1008 VectorType operator|(const CollectTemplate<std::vector>&) const {
1012 template <class Body>
1013 void foreach(Body&& body) const {
1014 for (auto& value : asVector()) {
1015 body(std::move(value));
1019 template <class Handler>
1020 bool apply(Handler&& handler) const {
1021 auto comparer = [&](const StorageType& a, const StorageType& b) {
1022 // swapped for minHeap
1023 return comparer_(selector_(b), selector_(a));
1025 auto heap = source_ | as<VectorType>();
1026 std::make_heap(heap.begin(), heap.end(), comparer);
1027 while (!heap.empty()) {
1028 std::pop_heap(heap.begin(), heap.end(), comparer);
1029 if (!handler(std::move(heap.back()))) {
1037 // Can only be run on and produce finite generators
1038 static constexpr bool infinite = false;
1041 template <class Source,
1043 class Gen = Generator<Value, Source>>
1044 Gen compose(GenImpl<Value, Source>&& source) const {
1045 return Gen(std::move(source.self()), selector_, comparer_);
1048 template <class Source,
1050 class Gen = Generator<Value, Source>>
1051 Gen compose(const GenImpl<Value, Source>& source) const {
1052 return Gen(source.self(), selector_, comparer_);
1057 * GroupBy - Group values by a given key selector, producing a sequence of
1060 * This type is usually used through the 'groupBy' helper function, like:
1064 * | groupBy([](const Place& p) {
1067 * | [](Group<std::string, Place>&& g) {
1068 * cout << g.key() << ": " << (g | first).description;
1071 template <class Selector>
1072 class GroupBy : public Operator<GroupBy<Selector>> {
1078 explicit GroupBy(Selector selector) : selector_(std::move(selector)) {}
1080 template <class Value,
1082 class ValueDecayed = typename std::decay<Value>::type,
1083 class Key = typename std::result_of<Selector(Value)>::type,
1084 class KeyDecayed = typename std::decay<Key>::type>
1087 Group<KeyDecayed, ValueDecayed>&&,
1088 Generator<Value, Source, ValueDecayed, Key, KeyDecayed>> {
1089 static_assert(!Source::infinite, "Cannot group infinite source!");
1094 Generator(Source source, Selector selector)
1095 : source_(std::move(source)), selector_(std::move(selector)) {}
1097 typedef Group<KeyDecayed, ValueDecayed> GroupType;
1099 template <class Handler>
1100 bool apply(Handler&& handler) const {
1101 std::unordered_map<KeyDecayed, typename GroupType::VectorType> groups;
1102 source_ | [&](Value value) {
1103 const Value& cv = value;
1104 auto& group = groups[selector_(cv)];
1105 group.push_back(std::forward<Value>(value));
1107 for (auto& kg : groups) {
1108 GroupType group(kg.first, std::move(kg.second));
1109 if (!handler(std::move(group))) {
1117 // Can only be run on and produce finite generators
1118 static constexpr bool infinite = false;
1121 template <class Source,
1123 class Gen = Generator<Value, Source>>
1124 Gen compose(GenImpl<Value, Source>&& source) const {
1125 return Gen(std::move(source.self()), selector_);
1128 template <class Source,
1130 class Gen = Generator<Value, Source>>
1131 Gen compose(const GenImpl<Value, Source>& source) const {
1132 return Gen(source.self(), selector_);
1137 * TypeAssertion - For verifying the exact type of the value produced by a
1138 * generator. Useful for testing and debugging, and acts as a no-op at runtime.
1139 * Pass-through at runtime. Used through the 'assert_type<>()' factory method
1142 * auto c = from(vector) | assert_type<int&>() | sum;
1145 template <class Expected>
1146 class TypeAssertion : public Operator<TypeAssertion<Expected>> {
1148 template <class Source, class Value>
1149 const Source& compose(const GenImpl<Value, Source>& source) const {
1150 static_assert(std::is_same<Expected, Value>::value,
1151 "assert_type() check failed");
1152 return source.self();
1155 template <class Source, class Value>
1156 Source&& compose(GenImpl<Value, Source>&& source) const {
1157 static_assert(std::is_same<Expected, Value>::value,
1158 "assert_type() check failed");
1159 return std::move(source.self());
1164 * Distinct - For filtering duplicates out of a sequence. A selector may be
1165 * provided to generate a key to uniquify for each value.
1167 * This type is usually used through the 'distinct' helper function, like:
1169 * auto closest = from(results)
1170 * | distinctBy([](Item& i) {
1175 template <class Selector>
1176 class Distinct : public Operator<Distinct<Selector>> {
1180 Distinct() = default;
1182 explicit Distinct(Selector selector) : selector_(std::move(selector)) {}
1184 template <class Value, class Source>
1185 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1189 typedef typename std::decay<Value>::type StorageType;
1191 // selector_ cannot be passed an rvalue or it would end up passing the husk
1192 // of a value to the downstream operators.
1193 typedef const StorageType& ParamType;
1195 typedef typename std::result_of<Selector(ParamType)>::type KeyType;
1196 typedef typename std::decay<KeyType>::type KeyStorageType;
1199 Generator(Source source, Selector selector)
1200 : source_(std::move(source)), selector_(std::move(selector)) {}
1202 template <class Body>
1203 void foreach(Body&& body) const {
1204 std::unordered_set<KeyStorageType> keysSeen;
1205 source_.foreach([&](Value value) {
1206 if (keysSeen.insert(selector_(ParamType(value))).second) {
1207 body(std::forward<Value>(value));
1212 template <class Handler>
1213 bool apply(Handler&& handler) const {
1214 std::unordered_set<KeyStorageType> keysSeen;
1215 return source_.apply([&](Value value) -> bool {
1216 if (keysSeen.insert(selector_(ParamType(value))).second) {
1217 return handler(std::forward<Value>(value));
1223 // While running distinct on an infinite sequence might produce a
1224 // conceptually finite sequence, it will take infinite time
1225 static constexpr bool infinite = Source::infinite;
1228 template <class Source,
1230 class Gen = Generator<Value, Source>>
1231 Gen compose(GenImpl<Value, Source>&& source) const {
1232 return Gen(std::move(source.self()), selector_);
1235 template <class Source,
1237 class Gen = Generator<Value, Source>>
1238 Gen compose(const GenImpl<Value, Source>& source) const {
1239 return Gen(source.self(), selector_);
1244 * Composer - Helper class for adapting pipelines into functors. Primarily used
1247 template <class Operators>
1252 explicit Composer(Operators op) : op_(std::move(op)) {}
1254 template <class Source,
1255 class Ret = decltype(
1256 std::declval<Operators>().compose(std::declval<Source>()))>
1257 Ret operator()(Source&& source) const {
1258 return op_.compose(std::forward<Source>(source));
1263 * Batch - For producing fixed-size batches of each value from a source.
1265 * This type is usually used through the 'batch' helper function:
1270 * | map([](const std::vector<int>& batch) {
1271 * return from(batch) | sum;
1275 class Batch : public Operator<Batch> {
1279 explicit Batch(size_t batchSize) : batchSize_(batchSize) {
1280 if (batchSize_ == 0) {
1281 throw std::invalid_argument("Batch size must be non-zero!");
1285 template <class Value,
1287 class StorageType = typename std::decay<Value>::type,
1288 class VectorType = std::vector<StorageType>>
1290 : public GenImpl<VectorType&,
1291 Generator<Value, Source, StorageType, VectorType>> {
1296 explicit Generator(Source source, size_t batchSize)
1297 : source_(std::move(source)), batchSize_(batchSize) {}
1299 template <class Handler>
1300 bool apply(Handler&& handler) const {
1302 batch_.reserve(batchSize_);
1303 bool shouldContinue = source_.apply([&](Value value) -> bool {
1304 batch_.push_back(std::forward<Value>(value));
1305 if (batch_.size() == batchSize_) {
1306 bool needMore = handler(batch_);
1310 // Always need more if the handler is not called.
1313 // Flush everything, if and only if `handler` hasn't returned false.
1314 if (shouldContinue && !batch_.empty()) {
1315 shouldContinue = handler(batch_);
1318 return shouldContinue;
1321 // Taking n-tuples of an infinite source is still infinite
1322 static constexpr bool infinite = Source::infinite;
1325 template <class Source,
1327 class Gen = Generator<Value, Source>>
1328 Gen compose(GenImpl<Value, Source>&& source) const {
1329 return Gen(std::move(source.self()), batchSize_);
1332 template <class Source,
1334 class Gen = Generator<Value, Source>>
1335 Gen compose(const GenImpl<Value, Source>& source) const {
1336 return Gen(source.self(), batchSize_);
1341 * Concat - For flattening generators of generators.
1343 * This type is usually used through the 'concat' static value, like:
1347 * | map([](Node& x) {
1348 * return from(x.neighbors)
1349 * | map([&](Node& y) {
1350 * return Edge(x, y);
1356 class Concat : public Operator<Concat> {
1360 template <class Inner,
1362 class InnerValue = typename std::decay<Inner>::type::ValueType>
1364 : public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1368 explicit Generator(Source source) : source_(std::move(source)) {}
1370 template <class Handler>
1371 bool apply(Handler&& handler) const {
1372 return source_.apply([&](Inner inner) -> bool {
1373 return inner.apply(std::forward<Handler>(handler));
1377 template <class Body>
1378 void foreach(Body&& body) const {
1379 source_.foreach([&](Inner inner) {
1380 inner.foreach(std::forward<Body>(body));
1384 // Resulting concatination is only finite if both Source and Inner are also
1385 // finite. In one sence, if dosn't make sence to call concat when the Inner
1386 // generator is infinite (you could just call first), so we could also just
1387 // static_assert if the inner is infinite. Taking the less restrictive
1389 static constexpr bool infinite =
1390 Source::infinite || std::decay<Inner>::type::infinite;
1393 template <class Value,
1395 class Gen = Generator<Value, Source>>
1396 Gen compose(GenImpl<Value, Source>&& source) const {
1397 return Gen(std::move(source.self()));
1400 template <class Value,
1402 class Gen = Generator<Value, Source>>
1403 Gen compose(const GenImpl<Value, Source>& source) const {
1404 return Gen(source.self());
1409 * RangeConcat - For flattening generators of iterables.
1411 * This type is usually used through the 'rconcat' static value, like:
1413 * map<int, vector<int>> adjacency;
1420 class RangeConcat : public Operator<RangeConcat> {
1422 RangeConcat() = default;
1424 template <class Range,
1426 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1428 : public GenImpl<InnerValue, Generator<Range, Source, InnerValue>> {
1432 explicit Generator(Source source) : source_(std::move(source)) {}
1434 template <class Body>
1435 void foreach(Body&& body) const {
1436 source_.foreach([&](Range range) {
1437 for (auto& value : range) {
1443 template <class Handler>
1444 bool apply(Handler&& handler) const {
1445 return source_.apply([&](Range range) -> bool {
1446 for (auto& value : range) {
1447 if (!handler(value)) {
1455 // This is similar to concat, except that the inner iterables all are finite
1456 // so the only thing that matters is that the source is infinite.
1457 static constexpr bool infinite = Source::infinite;
1460 template <class Value,
1462 class Gen = Generator<Value, Source>>
1463 Gen compose(GenImpl<Value, Source>&& source) const {
1464 return Gen(std::move(source.self()));
1467 template <class Value,
1469 class Gen = Generator<Value, Source>>
1470 Gen compose(const GenImpl<Value, Source>& source) const {
1471 return Gen(source.self());
1476 * GuardImpl - For handling exceptions from downstream computation. Requires the
1477 * type of exception to catch, and handler function to invoke in the event of
1478 * the exception. Note that the handler may:
1479 * 1) return true to continue processing the sequence
1480 * 2) return false to end the sequence immediately
1481 * 3) throw, to pass the exception to the next catch
1482 * The handler must match the signature 'bool(Exception&, Value)'.
1484 * This type is used through the `guard` helper, like so:
1487 * = byLine(STDIN_FILENO)
1488 * | guard<std::runtime_error>([](std::runtime_error& e,
1490 * LOG(ERROR) << sp << ": " << e.str();
1491 * return true; // continue processing subsequent lines
1496 * TODO(tjackson): Rename this back to Guard.
1498 template <class Exception, class ErrorHandler>
1499 class GuardImpl : public Operator<GuardImpl<Exception, ErrorHandler>> {
1500 ErrorHandler handler_;
1503 explicit GuardImpl(ErrorHandler handler) : handler_(std::move(handler)) {}
1505 template <class Value, class Source>
1506 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1508 ErrorHandler handler_;
1511 explicit Generator(Source source, ErrorHandler handler)
1512 : source_(std::move(source)), handler_(std::move(handler)) {}
1514 template <class Handler>
1515 bool apply(Handler&& handler) const {
1516 return source_.apply([&](Value value) -> bool {
1518 handler(std::forward<Value>(value));
1520 } catch (Exception& e) {
1521 return handler_(e, std::forward<Value>(value));
1526 // Just passes value though, length unaffected
1527 static constexpr bool infinite = Source::infinite;
1530 template <class Value,
1532 class Gen = Generator<Value, Source>>
1533 Gen compose(GenImpl<Value, Source>&& source) const {
1534 return Gen(std::move(source.self()), handler_);
1537 template <class Value,
1539 class Gen = Generator<Value, Source>>
1540 Gen compose(const GenImpl<Value, Source>& source) const {
1541 return Gen(source.self(), handler_);
1546 * Dereference - For dereferencing a sequence of pointers while filtering out
1549 * This type is usually used through the 'dereference' static value, like:
1551 * auto refs = from(ptrs) | dereference;
1553 class Dereference : public Operator<Dereference> {
1555 Dereference() = default;
1557 template <class Value,
1559 class Result = decltype(*std::declval<Value>())>
1560 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1564 explicit Generator(Source source) : source_(std::move(source)) {}
1566 template <class Body>
1567 void foreach(Body&& body) const {
1568 source_.foreach([&](Value value) {
1570 return body(*std::forward<Value>(value));
1575 template <class Handler>
1576 bool apply(Handler&& handler) const {
1577 return source_.apply([&](Value value) -> bool {
1579 return handler(*std::forward<Value>(value));
1585 // Just passes value though, length unaffected
1586 static constexpr bool infinite = Source::infinite;
1589 template <class Source,
1591 class Gen = Generator<Value, Source>>
1592 Gen compose(GenImpl<Value, Source>&& source) const {
1593 return Gen(std::move(source.self()));
1596 template <class Source,
1598 class Gen = Generator<Value, Source>>
1599 Gen compose(const GenImpl<Value, Source>& source) const {
1600 return Gen(source.self());
1605 * Indirect - For producing a sequence of the addresses of the values in the
1608 * This type is usually used through the 'indirect' static value, like:
1610 * auto ptrs = from(refs) | indirect;
1612 class Indirect : public Operator<Indirect> {
1614 Indirect() = default;
1616 template <class Value,
1618 class Result = typename std::remove_reference<Value>::type*>
1619 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1621 static_assert(!std::is_rvalue_reference<Value>::value,
1622 "Cannot use indirect on an rvalue");
1625 explicit Generator(Source source) : source_(std::move(source)) {}
1627 template <class Body>
1628 void foreach(Body&& body) const {
1629 source_.foreach([&](Value value) {
1630 return body(&std::forward<Value>(value));
1634 template <class Handler>
1635 bool apply(Handler&& handler) const {
1636 return source_.apply([&](Value value) -> bool {
1637 return handler(&std::forward<Value>(value));
1641 // Just passes value though, length unaffected
1642 static constexpr bool infinite = Source::infinite;
1645 template <class Source,
1647 class Gen = Generator<Value, Source>>
1648 Gen compose(GenImpl<Value, Source>&& source) const {
1649 return Gen(std::move(source.self()));
1652 template <class Source,
1654 class Gen = Generator<Value, Source>>
1655 Gen compose(const GenImpl<Value, Source>& source) const {
1656 return Gen(source.self());
1661 * Cycle - For repeating a sequence forever.
1663 * This type is usually used through the 'cycle' static value, like:
1670 * or in the finite case:
1672 * auto thrice = g | cycle(3);
1674 template <bool forever>
1675 class Cycle : public Operator<Cycle<forever>> {
1676 off_t limit_; // not used if forever == true
1680 explicit Cycle(off_t limit) : limit_(limit) {
1683 "Cycle limit constructor should not be used when forever == true.");
1686 template <class Value, class Source>
1687 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1692 explicit Generator(Source source, off_t limit)
1693 : source_(std::move(source)), limit_(limit) {}
1695 template <class Handler>
1696 bool apply(Handler&& handler) const {
1698 auto handler2 = [&](Value value) {
1699 cont = handler(std::forward<Value>(value));
1702 // Becomes an infinte loop if forever == true
1703 for (off_t count = 0; (forever || count != limit_); ++count) {
1705 source_.apply(handler2);
1713 // This is the hardest one to infer. If we are simply doing a finite cycle,
1714 // then (gen | cycle(n)) is infinite if and only if gen is infinite.
1715 // However, if we are doing an infinite cycle, (gen | cycle) is infinite
1716 // unless gen is empty. However, we will always mark (gen | cycle) as
1717 // infinite, because patterns such as (gen | cycle | count) can either take
1718 // on exactly one value, or infinite loop.
1719 static constexpr bool infinite = forever || Source::infinite;
1722 template <class Source,
1724 class Gen = Generator<Value, Source>>
1725 Gen compose(GenImpl<Value, Source>&& source) const {
1726 return Gen(std::move(source.self()), limit_);
1729 template <class Source,
1731 class Gen = Generator<Value, Source>>
1732 Gen compose(const GenImpl<Value, Source>& source) const {
1733 return Gen(source.self(), limit_);
1737 * Convenience function for finite cycles used like:
1739 * auto tripled = gen | cycle(3);
1741 Cycle<false> operator()(off_t limit) const { return Cycle<false>(limit); }
1745 ******************************* Sinks *****************************************
1749 * FoldLeft - Left-associative functional fold. For producing an aggregate value
1750 * from a seed and a folder function. Useful for custom aggregators on a
1753 * This type is primarily used through the 'foldl' helper method, like:
1755 * double movingAverage = from(values)
1756 * | foldl(0.0, [](double avg, double sample) {
1757 * return sample * 0.1 + avg * 0.9;
1760 template <class Seed, class Fold>
1761 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
1766 FoldLeft() = default;
1767 FoldLeft(Seed seed, Fold fold)
1768 : seed_(std::move(seed)), fold_(std::move(fold)) {}
1770 template <class Source, class Value>
1771 Seed compose(const GenImpl<Value, Source>& source) const {
1772 static_assert(!Source::infinite, "Cannot foldl infinite source");
1774 source | [&](Value v) {
1775 accum = fold_(std::move(accum), std::forward<Value>(v));
1782 * First - For finding the first value in a sequence.
1784 * This type is primarily used through the 'first' static value, like:
1786 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1788 class First : public Operator<First> {
1792 template <class Source,
1794 class StorageType = typename std::decay<Value>::type>
1795 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1796 Optional<StorageType> accum;
1797 source | [&](Value v) -> bool {
1798 accum = std::forward<Value>(v);
1806 * IsEmpty - a helper class for isEmpty and notEmpty
1808 * Essentially returns 'result' if the source is empty. Note that this cannot be
1809 * called on an infinite source, because then there is only one possible return
1813 * Used primarily through 'isEmpty' and 'notEmpty' static values
1815 * bool hasPrimes = g | filter(prime) | notEmpty;
1816 * bool lacksEvens = g | filter(even) | isEmpty;
1818 * Also used in the implementation of 'any' and 'all'
1820 template <bool emptyResult>
1821 class IsEmpty : public Operator<IsEmpty<emptyResult>> {
1823 IsEmpty() = default;
1825 template <class Source, class Value>
1826 bool compose(const GenImpl<Value, Source>& source) const {
1827 static_assert(!Source::infinite,
1828 "Cannot call 'all', 'any', 'isEmpty', or 'notEmpty' on "
1829 "infinite source. 'all' and 'isEmpty' will either return "
1830 "false or hang. 'any' or 'notEmpty' will either return true "
1832 bool ans = emptyResult;
1834 [&](Value /* v */) -> bool {
1843 * Reduce - Functional reduce, for recursively combining values from a source
1844 * using a reducer function until there is only one item left. Useful for
1845 * combining values when an empty sequence doesn't make sense.
1847 * This type is primarily used through the 'reduce' helper method, like:
1849 * sring longest = from(names)
1850 * | reduce([](string&& best, string& current) {
1851 * return best.size() >= current.size() ? best : current;
1854 template <class Reducer>
1855 class Reduce : public Operator<Reduce<Reducer>> {
1860 explicit Reduce(Reducer reducer) : reducer_(std::move(reducer)) {}
1862 template <class Source,
1864 class StorageType = typename std::decay<Value>::type>
1865 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1866 static_assert(!Source::infinite, "Cannot reduce infinite source");
1867 Optional<StorageType> accum;
1868 source | [&](Value v) {
1869 if (accum.hasValue()) {
1870 accum = reducer_(std::move(accum.value()), std::forward<Value>(v));
1872 accum = std::forward<Value>(v);
1880 * Count - for simply counting the items in a collection.
1882 * This type is usually used through its singleton, 'count':
1884 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1886 class Count : public Operator<Count> {
1890 template <class Source, class Value>
1891 size_t compose(const GenImpl<Value, Source>& source) const {
1892 static_assert(!Source::infinite, "Cannot count infinite source");
1893 return foldl(size_t(0),
1894 [](size_t accum, Value /* v */) { return accum + 1; })
1900 * Sum - For simply summing up all the values from a source.
1902 * This type is usually used through its singleton, 'sum':
1904 * auto gaussSum = seq(1, 100) | sum;
1906 class Sum : public Operator<Sum> {
1910 template <class Source,
1912 class StorageType = typename std::decay<Value>::type>
1913 StorageType compose(const GenImpl<Value, Source>& source) const {
1914 static_assert(!Source::infinite, "Cannot sum infinite source");
1915 return foldl(StorageType(0),
1916 [](StorageType&& accum, Value v) {
1917 return std::move(accum) + std::forward<Value>(v);
1923 * Contains - For testing whether a value matching the given value is contained
1926 * This type should be used through the 'contains' helper method, like:
1928 * bool contained = seq(1, 10) | map(square) | contains(49);
1930 template <class Needle>
1931 class Contains : public Operator<Contains<Needle>> {
1935 explicit Contains(Needle needle) : needle_(std::move(needle)) {}
1937 template <class Source,
1939 class StorageType = typename std::decay<Value>::type>
1940 bool compose(const GenImpl<Value, Source>& source) const {
1941 static_assert(!Source::infinite,
1942 "Calling contains on an infinite source might cause "
1943 "an infinite loop.");
1944 return !(source | [this](Value value) {
1945 return !(needle_ == std::forward<Value>(value));
1951 * Min - For a value which minimizes a key, where the key is determined by a
1952 * given selector, and compared by given comparer.
1954 * This type is usually used through the singletone 'min' or through the helper
1955 * functions 'minBy' and 'maxBy'.
1957 * auto oldest = from(people)
1958 * | minBy([](Person& p) {
1959 * return p.dateOfBirth;
1962 template <class Selector, class Comparer>
1963 class Min : public Operator<Min<Selector, Comparer>> {
1967 template <typename T>
1968 const T& asConst(const T& t) const {
1975 explicit Min(Selector selector) : selector_(std::move(selector)) {}
1977 Min(Selector selector, Comparer comparer)
1978 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
1980 template <class Value,
1982 class StorageType = typename std::decay<Value>::type,
1983 class Key = typename std::decay<
1984 typename std::result_of<Selector(Value)>::type>::type>
1985 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1986 static_assert(!Source::infinite,
1987 "Calling min or max on an infinite source will cause "
1988 "an infinite loop.");
1989 Optional<StorageType> min;
1990 Optional<Key> minKey;
1991 source | [&](Value v) {
1992 Key key = selector_(asConst(v)); // so that selector_ cannot mutate v
1993 if (!minKey.hasValue() || comparer_(key, minKey.value())) {
1994 minKey = std::move(key);
1995 min = std::forward<Value>(v);
2003 * Append - For collecting values from a source into a given output container
2006 * This type is usually used through the helper function 'appendTo', like:
2008 * vector<int64_t> ids;
2009 * from(results) | map([](Person& p) { return p.id })
2012 template <class Collection>
2013 class Append : public Operator<Append<Collection>> {
2014 Collection* collection_;
2017 explicit Append(Collection* collection) : collection_(collection) {}
2019 template <class Value, class Source>
2020 Collection& compose(const GenImpl<Value, Source>& source) const {
2021 static_assert(!Source::infinite, "Cannot appendTo with infinite source");
2022 source | [&](Value v) {
2023 collection_->insert(collection_->end(), std::forward<Value>(v));
2025 return *collection_;
2030 * Collect - For collecting values from a source in a collection of the desired
2033 * This type is usually used through the helper function 'as', like:
2035 * std::string upper = from(stringPiece)
2037 * | as<std::string>();
2039 template <class Collection>
2040 class Collect : public Operator<Collect<Collection>> {
2042 Collect() = default;
2044 template <class Value,
2046 class StorageType = typename std::decay<Value>::type>
2047 Collection compose(const GenImpl<Value, Source>& source) const {
2048 static_assert(!Source::infinite,
2049 "Cannot convert infinite source to object with as.");
2050 Collection collection;
2051 source | [&](Value v) {
2052 collection.insert(collection.end(), std::forward<Value>(v));
2059 * CollectTemplate - For collecting values from a source in a collection
2060 * constructed using the specified template type. Given the type of values
2061 * produced by the given generator, the collection type will be:
2062 * Container<Value, Allocator<Value>>
2064 * The allocator defaults to std::allocator, so this may be used for the STL
2065 * containers by simply using operators like 'as<set>', 'as<deque>',
2066 * 'as<vector>'. 'as', here is the helper method which is the usual means of
2067 * constructing this operator.
2071 * set<string> uniqueNames = from(names) | as<set>();
2073 template <template <class, class> class Container,
2074 template <class> class Allocator>
2075 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
2077 CollectTemplate() = default;
2079 template <class Value,
2081 class StorageType = typename std::decay<Value>::type,
2082 class Collection = Container<StorageType, Allocator<StorageType>>>
2083 Collection compose(const GenImpl<Value, Source>& source) const {
2084 static_assert(!Source::infinite,
2085 "Cannot convert infinite source to object with as.");
2086 Collection collection;
2087 source | [&](Value v) {
2088 collection.insert(collection.end(), std::forward<Value>(v));
2095 * UnwrapOr - For unwrapping folly::Optional values, or providing the given
2096 * fallback value. Usually used through the 'unwrapOr' helper like so:
2098 * auto best = from(scores) | max | unwrapOr(-1);
2100 * Note that the fallback value needn't match the value in the Optional it is
2101 * unwrapping. If mis-matched types are supported, the common type of the two is
2102 * returned by value. If the types match, a reference (T&& > T& > const T&) is
2108 explicit UnwrapOr(T&& value) : value_(std::move(value)) {}
2109 explicit UnwrapOr(const T& value) : value_(value) {}
2111 T& value() { return value_; }
2112 const T& value() const { return value_; }
2119 T&& operator|(Optional<T>&& opt, UnwrapOr<T>&& fallback) {
2120 if (T* p = opt.get_pointer()) {
2121 return std::move(*p);
2123 return std::move(fallback.value());
2127 T& operator|(Optional<T>& opt, UnwrapOr<T>& fallback) {
2128 if (T* p = opt.get_pointer()) {
2131 return fallback.value();
2135 const T& operator|(const Optional<T>& opt, const UnwrapOr<T>& fallback) {
2136 if (const T* p = opt.get_pointer()) {
2139 return fallback.value();
2142 // Mixed type unwrapping always returns values, moving where possible
2145 class R = typename std::enable_if<
2146 !std::is_same<T, U>::value,
2147 typename std::common_type<T, U>::type>::type>
2148 R operator|(Optional<T>&& opt, UnwrapOr<U>&& fallback) {
2149 if (T* p = opt.get_pointer()) {
2150 return std::move(*p);
2152 return std::move(fallback.value());
2157 class R = typename std::enable_if<
2158 !std::is_same<T, U>::value,
2159 typename std::common_type<T, U>::type>::type>
2160 R operator|(const Optional<T>& opt, UnwrapOr<U>&& fallback) {
2161 if (const T* p = opt.get_pointer()) {
2164 return std::move(fallback.value());
2169 class R = typename std::enable_if<
2170 !std::is_same<T, U>::value,
2171 typename std::common_type<T, U>::type>::type>
2172 R operator|(Optional<T>&& opt, const UnwrapOr<U>& fallback) {
2173 if (T* p = opt.get_pointer()) {
2174 return std::move(*p);
2176 return fallback.value();
2181 class R = typename std::enable_if<
2182 !std::is_same<T, U>::value,
2183 typename std::common_type<T, U>::type>::type>
2184 R operator|(const Optional<T>& opt, const UnwrapOr<U>& fallback) {
2185 if (const T* p = opt.get_pointer()) {
2188 return fallback.value();
2192 * Unwrap - For unwrapping folly::Optional values in a folly::gen style. Usually
2193 * used through the 'unwrap' instace like so:
2195 * auto best = from(scores) | max | unwrap; // may throw
2200 T&& operator|(Optional<T>&& opt, const Unwrap&) {
2201 return std::move(opt.value());
2205 T& operator|(Optional<T>& opt, const Unwrap&) {
2210 const T& operator|(const Optional<T>& opt, const Unwrap&) {
2217 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
2219 template <class Value>
2220 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
2223 virtual ~WrapperBase() noexcept {}
2224 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
2225 virtual void foreach(const std::function<void(Value)>& body) const = 0;
2226 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
2229 template <class Wrapped>
2230 class WrapperImpl : public WrapperBase {
2234 explicit WrapperImpl(Wrapped wrapped) : wrapped_(std::move(wrapped)) {}
2236 virtual bool apply(const std::function<bool(Value)>& handler) const {
2237 return wrapped_.apply(handler);
2240 virtual void foreach(const std::function<void(Value)>& body) const {
2241 wrapped_.foreach(body);
2244 virtual std::unique_ptr<const WrapperBase> clone() const {
2245 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
2249 std::unique_ptr<const WrapperBase> wrapper_;
2252 template <class Self>
2253 /* implicit */ VirtualGen(Self source)
2254 : wrapper_(new WrapperImpl<Self>(std::move(source))) {}
2256 VirtualGen(VirtualGen&& source) noexcept
2257 : wrapper_(std::move(source.wrapper_)) {}
2259 VirtualGen(const VirtualGen& source) : wrapper_(source.wrapper_->clone()) {}
2261 VirtualGen& operator=(const VirtualGen& source) {
2262 wrapper_.reset(source.wrapper_->clone());
2266 VirtualGen& operator=(VirtualGen&& source) noexcept {
2267 wrapper_ = std::move(source.wrapper_);
2271 bool apply(const std::function<bool(Value)>& handler) const {
2272 return wrapper_->apply(handler);
2275 void foreach(const std::function<void(Value)>& body) const {
2276 wrapper_->foreach(body);
2281 * non-template operators, statically defined to avoid the need for anything but
2284 constexpr detail::Sum sum{};
2286 constexpr detail::Count count{};
2288 constexpr detail::First first{};
2290 constexpr detail::IsEmpty<true> isEmpty{};
2292 constexpr detail::IsEmpty<false> notEmpty{};
2294 constexpr detail::Min<Identity, Less> min{};
2296 constexpr detail::Min<Identity, Greater> max{};
2298 constexpr detail::Order<Identity> order{};
2300 constexpr detail::Distinct<Identity> distinct{};
2302 constexpr detail::Map<Move> move{};
2304 constexpr detail::Concat concat{};
2306 constexpr detail::RangeConcat rconcat{};
2308 constexpr detail::Cycle<true> cycle{};
2310 constexpr detail::Dereference dereference{};
2312 constexpr detail::Indirect indirect{};
2314 constexpr detail::Unwrap unwrap{};
2316 template <class Number>
2317 inline detail::Take take(Number count) {
2319 throw std::invalid_argument("Negative value passed to take()");
2321 return detail::Take(static_cast<size_t>(count));
2324 inline detail::Stride stride(size_t s) { return detail::Stride(s); }
2326 template <class Random = std::default_random_engine>
2327 inline detail::Sample<Random> sample(size_t count, Random rng = Random()) {
2328 return detail::Sample<Random>(count, std::move(rng));
2331 inline detail::Skip skip(size_t count) { return detail::Skip(count); }
2333 inline detail::Batch batch(size_t batchSize) {
2334 return detail::Batch(batchSize);
2339 #pragma GCC diagnostic pop