2 * Copyright 2017 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"
29 * ArgumentReference - For determining ideal argument type to receive a value.
32 struct ArgumentReference
33 : public std::conditional<
34 std::is_reference<T>::value,
35 T, // T& -> T&, T&& -> T&&, const T& -> const T&
36 typename std::conditional<std::is_const<T>::value,
37 T&, // const int -> const int&
42 * Group - The output objects from the GroupBy operator
44 template <class Key, class Value>
45 class Group : public GenImpl<Value&&, Group<Key, Value>> {
47 static_assert(!std::is_reference<Key>::value &&
48 !std::is_reference<Value>::value,
49 "Key and Value must be decayed types");
51 typedef std::vector<Value> VectorType;
53 typedef Value ValueType;
55 Group(Key key, VectorType values)
56 : key_(std::move(key)), values_(std::move(values)) {}
58 const Key& key() const { return key_; }
60 size_t size() const { return values_.size(); }
61 const VectorType& values() const { return values_; }
62 VectorType& values() { return values_; }
64 VectorType operator|(const detail::Collect<VectorType>&) const {
68 VectorType operator|(const detail::CollectTemplate<std::vector>&) const {
73 void foreach(Body&& body) const {
74 for (auto& value : values_) {
75 body(std::move(value));
79 template <class Handler>
80 bool apply(Handler&& handler) const {
81 for (auto& value : values_) {
82 if (!handler(std::move(value))) {
89 // GroupBy only takes in finite generators, so we only have finite groups
90 static constexpr bool infinite = false;
94 mutable VectorType values_;
99 // Classes used for the implementation of Sources, Operators, and Sinks
102 ******************************* Sources ***************************************
106 * ReferencedSource - Generate values from an STL-like container using
107 * iterators from .begin() until .end(). Value type defaults to the type of
108 * *container->begin(). For std::vector<int>, this would be int&. Note that the
109 * value here is a reference, so the values in the vector will be passed by
110 * reference to downstream operators.
112 * This type is primarily used through the 'from' helper method, like:
114 * string& longestName = from(names)
115 * | maxBy([](string& s) { return s.size() });
117 template <class Container, class Value>
118 class ReferencedSource
119 : public GenImpl<Value, ReferencedSource<Container, Value>> {
120 Container* container_;
123 explicit ReferencedSource(Container* container) : container_(container) {}
125 template <class Body>
126 void foreach(Body&& body) const {
127 for (auto& value : *container_) {
128 body(std::forward<Value>(value));
132 template <class Handler>
133 bool apply(Handler&& handler) const {
134 for (auto& value : *container_) {
135 if (!handler(std::forward<Value>(value))) {
142 // from takes in a normal stl structure, which are all finite
143 static constexpr bool infinite = false;
147 * CopiedSource - For producing values from eagerly from a sequence of values
148 * whose storage is owned by this class. Useful for preparing a generator for
149 * use after a source collection will no longer be available, or for when the
150 * values are specified literally with an initializer list.
152 * This type is primarily used through the 'fromCopy' function, like:
154 * auto sourceCopy = fromCopy(makeAVector());
155 * auto sum = sourceCopy | sum;
156 * auto max = sourceCopy | max;
158 * Though it is also used for the initializer_list specialization of from().
160 template <class StorageType, class Container>
162 : public GenImpl<const StorageType&, CopiedSource<StorageType, Container>> {
163 static_assert(!std::is_reference<StorageType>::value,
164 "StorageType must be decayed");
167 // Generator objects are often copied during normal construction as they are
168 // encapsulated by downstream generators. It would be bad if this caused
169 // a copy of the entire container each time, and since we're only exposing a
170 // const reference to the value, it's safe to share it between multiple
172 static_assert(!std::is_reference<Container>::value,
173 "Can't copy into a reference");
174 std::shared_ptr<const Container> copy_;
177 typedef Container ContainerType;
179 template <class SourceContainer>
180 explicit CopiedSource(const SourceContainer& container)
181 : copy_(new Container(begin(container), end(container))) {}
183 explicit CopiedSource(Container&& container)
184 : copy_(new Container(std::move(container))) {}
186 // To enable re-use of cached results.
187 CopiedSource(const CopiedSource<StorageType, Container>& source)
188 : copy_(source.copy_) {}
190 template <class Body>
191 void foreach(Body&& body) const {
192 for (const auto& value : *copy_) {
197 template <class Handler>
198 bool apply(Handler&& handler) const {
199 // The collection may be reused by others, we can't allow it to be changed.
200 for (const auto& value : *copy_) {
201 if (!handler(value)) {
208 // from takes in a normal stl structure, which are all finite
209 static constexpr bool infinite = false;
213 * RangeSource - For producing values from a folly::Range. Useful for referring
214 * to a slice of some container.
216 * This type is primarily used through the 'from' function, like:
218 * auto rangeSource = from(folly::range(v.begin(), v.end()));
219 * auto sum = rangeSource | sum;
221 * Reminder: Be careful not to invalidate iterators when using ranges like this.
223 template <class Iterator>
224 class RangeSource : public GenImpl<typename Range<Iterator>::reference,
225 RangeSource<Iterator>> {
226 Range<Iterator> range_;
229 RangeSource() = default;
230 explicit RangeSource(Range<Iterator> range) : range_(std::move(range)) {}
232 template <class Handler>
233 bool apply(Handler&& handler) const {
234 for (auto& value : range_) {
235 if (!handler(value)) {
242 template <class Body>
243 void foreach(Body&& body) const {
244 for (auto& value : range_) {
249 // folly::Range only supports finite ranges
250 static constexpr bool infinite = false;
254 * Sequence - For generating values from beginning value, incremented along the
255 * way with the ++ and += operators. Iteration may continue indefinitely.
256 * Value type specified explicitly.
258 * This type is primarily used through the 'seq' and 'range' function, like:
260 * int total = seq(1, 10) | sum;
261 * auto indexes = range(0, 10);
262 * auto endless = seq(0); // 0, 1, 2, 3, ...
264 template <class Value, class SequenceImpl>
265 class Sequence : public GenImpl<const Value&, Sequence<Value, SequenceImpl>> {
266 static_assert(!std::is_reference<Value>::value &&
267 !std::is_const<Value>::value,
268 "Value mustn't be const or ref.");
273 explicit Sequence(Value start, SequenceImpl impl)
274 : start_(std::move(start)), impl_(std::move(impl)) {}
276 template <class Handler>
277 bool apply(Handler&& handler) const {
278 for (Value current = start_; impl_.test(current); impl_.step(current)) {
279 if (!handler(current)) {
286 template <class Body>
287 void foreach(Body&& body) const {
288 for (Value current = start_; impl_.test(current); impl_.step(current)) {
293 // Let the implementation say if we are infinite or not
294 static constexpr bool infinite = SequenceImpl::infinite;
298 * Sequence implementations (range, sequence, infinite, with/without step)
300 template <class Value>
305 explicit RangeImpl(Value end) : end_(std::move(end)) {}
306 bool test(const Value& current) const { return current < end_; }
307 void step(Value& current) const { ++current; }
308 static constexpr bool infinite = false;
311 template <class Value, class Distance>
312 class RangeWithStepImpl {
317 explicit RangeWithStepImpl(Value end, Distance step)
318 : end_(std::move(end)), step_(std::move(step)) {}
319 bool test(const Value& current) const { return current < end_; }
320 void step(Value& current) const { current += step_; }
321 static constexpr bool infinite = false;
324 template <class Value>
329 explicit SeqImpl(Value end) : end_(std::move(end)) {}
330 bool test(const Value& current) const { return current <= end_; }
331 void step(Value& current) const { ++current; }
332 static constexpr bool infinite = false;
335 template <class Value, class Distance>
336 class SeqWithStepImpl {
341 explicit SeqWithStepImpl(Value end, Distance step)
342 : end_(std::move(end)), step_(std::move(step)) {}
343 bool test(const Value& current) const { return current <= end_; }
344 void step(Value& current) const { current += step_; }
345 static constexpr bool infinite = false;
348 template <class Value>
351 bool test(const Value& /* current */) const { return true; }
352 void step(Value& current) const { ++current; }
353 static constexpr bool infinite = true;
357 * GenratorBuilder - Helper for GENERTATOR macro.
359 template <class Value>
360 struct GeneratorBuilder {
361 template <class Source,
362 class Yield = detail::Yield<Value, Source>>
363 Yield operator+(Source&& source) {
364 return Yield(std::forward<Source>(source));
369 * Yield - For producing values from a user-defined generator by way of a
372 template <class Value, class Source>
373 class Yield : public GenImpl<Value, Yield<Value, Source>> {
377 explicit Yield(Source source) : source_(std::move(source)) {}
379 template <class Handler>
380 bool apply(Handler&& handler) const {
382 auto body = [&](Value value) {
383 if (!handler(std::forward<Value>(value))) {
395 template <class Body>
396 void foreach(Body&& body) const {
397 source_(std::forward<Body>(body));
401 template <class Value>
402 class Empty : public GenImpl<Value, Empty<Value>> {
404 template <class Handler>
405 bool apply(Handler&&) const {
409 template <class Body>
410 void foreach(Body&&) const {}
412 // No values, so finite
413 static constexpr bool infinite = false;
416 template <class Value>
417 class SingleReference : public GenImpl<Value&, SingleReference<Value>> {
418 static_assert(!std::is_reference<Value>::value,
419 "SingleReference requires non-ref types");
423 explicit SingleReference(Value& ref) : ptr_(&ref) {}
425 template <class Handler>
426 bool apply(Handler&& handler) const {
427 return handler(*ptr_);
430 template <class Body>
431 void foreach(Body&& body) const {
435 // One value, so finite
436 static constexpr bool infinite = false;
439 template <class Value>
440 class SingleCopy : public GenImpl<const Value&, SingleCopy<Value>> {
441 static_assert(!std::is_reference<Value>::value,
442 "SingleCopy requires non-ref types");
446 explicit SingleCopy(Value value) : value_(std::forward<Value>(value)) {}
448 template <class Handler>
449 bool apply(Handler&& handler) const {
450 return handler(value_);
453 template <class Body>
454 void foreach(Body&& body) const {
458 // One value, so finite
459 static constexpr bool infinite = false;
463 ***************************** Operators ***************************************
467 * Map - For producing a sequence of values by passing each value from a source
468 * collection through a predicate.
470 * This type is usually used through the 'map' or 'mapped' helper function:
472 * auto squares = seq(1, 10) | map(square) | asVector;
474 template <class Predicate>
475 class Map : public Operator<Map<Predicate>> {
481 explicit Map(Predicate pred) : pred_(std::move(pred)) {}
483 template <class Value,
485 class Result = typename ArgumentReference<
486 typename std::result_of<Predicate(Value)>::type>::type>
487 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
492 explicit Generator(Source source, const Predicate& pred)
493 : source_(std::move(source)), pred_(pred) {}
495 template <class Body>
496 void foreach(Body&& body) const {
498 [&](Value value) { body(pred_(std::forward<Value>(value))); });
501 template <class Handler>
502 bool apply(Handler&& handler) const {
503 return source_.apply([&](Value value) {
504 return handler(pred_(std::forward<Value>(value)));
508 static constexpr bool infinite = Source::infinite;
511 template <class Source,
513 class Gen = Generator<Value, Source>>
514 Gen compose(GenImpl<Value, Source>&& source) const {
515 return Gen(std::move(source.self()), pred_);
518 template <class Source,
520 class Gen = Generator<Value, Source>>
521 Gen compose(const GenImpl<Value, Source>& source) const {
522 return Gen(source.self(), pred_);
527 * Filter - For filtering values from a source sequence by a predicate.
529 * This type is usually used through the 'filter' helper function, like:
531 * auto nonEmpty = from(strings)
532 * | filter([](const string& str) -> bool {
533 * return !str.empty();
536 * Note that if no predicate is provided, the values are casted to bool and
537 * filtered based on that. So if pointers is a vector of pointers,
539 * auto nonNull = from(pointers) | filter();
541 * will give a vector of all the pointers != nullptr.
543 template <class Predicate>
544 class Filter : public Operator<Filter<Predicate>> {
549 explicit Filter(Predicate pred) : pred_(std::move(pred)) {}
551 template <class Value, class Source>
552 class Generator : public GenImpl<Value, Generator<Value, Source>> {
557 explicit Generator(Source source, const Predicate& pred)
558 : source_(std::move(source)), pred_(pred) {}
560 template <class Body>
561 void foreach(Body&& body) const {
562 source_.foreach([&](Value value) {
563 // NB: Argument not forwarded to avoid accidental move-construction
565 body(std::forward<Value>(value));
570 template <class Handler>
571 bool apply(Handler&& handler) const {
572 return source_.apply([&](Value value) -> bool {
573 // NB: Argument not forwarded to avoid accidental move-construction
575 return handler(std::forward<Value>(value));
581 static constexpr bool infinite = Source::infinite;
584 template <class Source,
586 class Gen = Generator<Value, Source>>
587 Gen compose(GenImpl<Value, Source>&& source) const {
588 return Gen(std::move(source.self()), pred_);
591 template <class Source,
593 class Gen = Generator<Value, Source>>
594 Gen compose(const GenImpl<Value, Source>& source) const {
595 return Gen(source.self(), pred_);
600 * Until - For producing values from a source until a predicate is satisfied.
602 * This type is usually used through the 'until' helper function, like:
604 * auto best = from(sortedItems)
605 * | until([](Item& item) { return item.score > 100; })
608 template <class Predicate>
609 class Until : public Operator<Until<Predicate>> {
614 explicit Until(Predicate pred) : pred_(std::move(pred)) {}
616 template <class Value, class Source>
617 class Generator : public GenImpl<Value, Generator<Value, Source>> {
622 explicit Generator(Source source, const Predicate& pred)
623 : source_(std::move(source)), pred_(pred) {}
625 template <class Handler>
626 bool apply(Handler&& handler) const {
627 bool cancelled = false;
628 source_.apply([&](Value value) -> bool {
629 if (pred_(value)) { // un-forwarded to disable move
632 if (!handler(std::forward<Value>(value))) {
641 // Theoretically an 'until' might stop an infinite
642 static constexpr bool infinite = false;
645 template <class Source,
647 class Gen = Generator<Value, Source>>
648 Gen compose(GenImpl<Value, Source>&& source) const {
649 return Gen(std::move(source.self()), pred_);
652 template <class Source,
654 class Gen = Generator<Value, Source>>
655 Gen compose(const GenImpl<Value, Source>& source) const {
656 return Gen(source.self(), pred_);
661 * Take - For producing up to N values from a source.
663 * This type is usually used through the 'take' helper function, like:
665 * auto best = from(docs)
666 * | orderByDescending(scoreDoc)
669 class Take : public Operator<Take> {
673 explicit Take(size_t count) : count_(count) {}
675 template <class Value, class Source>
676 class Generator : public GenImpl<Value, Generator<Value, Source>> {
681 explicit Generator(Source source, size_t count)
682 : source_(std::move(source)), count_(count) {}
684 template <class Handler>
685 bool apply(Handler&& handler) const {
690 bool cancelled = false;
691 source_.apply([&](Value value) -> bool {
692 if (!handler(std::forward<Value>(value))) {
701 // take will stop an infinite generator
702 static constexpr bool infinite = false;
705 template <class Source,
707 class Gen = Generator<Value, Source>>
708 Gen compose(GenImpl<Value, Source>&& source) const {
709 return Gen(std::move(source.self()), count_);
712 template <class Source,
714 class Gen = Generator<Value, Source>>
715 Gen compose(const GenImpl<Value, Source>& source) const {
716 return Gen(source.self(), count_);
721 * Stride - For producing every Nth value from a source.
723 * This type is usually used through the 'stride' helper function, like:
725 * auto half = from(samples)
728 class Stride : public Operator<Stride> {
732 explicit Stride(size_t stride) : stride_(stride) {
734 throw std::invalid_argument("stride must not be 0");
738 template <class Value, class Source>
739 class Generator : public GenImpl<Value, Generator<Value, Source>> {
744 explicit Generator(Source source, size_t stride)
745 : source_(std::move(source)), stride_(stride) {}
747 template <class Handler>
748 bool apply(Handler&& handler) const {
749 size_t distance = stride_;
750 return source_.apply([&](Value value) -> bool {
751 if (++distance >= stride_) {
752 if (!handler(std::forward<Value>(value))) {
761 template <class Body>
762 void foreach(Body&& body) const {
763 size_t distance = stride_;
764 source_.foreach([&](Value value) {
765 if (++distance >= stride_) {
766 body(std::forward<Value>(value));
772 // Taking every Nth of an infinite list is still infinte
773 static constexpr bool infinite = Source::infinite;
776 template <class Source,
778 class Gen = Generator<Value, Source>>
779 Gen compose(GenImpl<Value, Source>&& source) const {
780 return Gen(std::move(source.self()), stride_);
783 template <class Source,
785 class Gen = Generator<Value, Source>>
786 Gen compose(const GenImpl<Value, Source>& source) const {
787 return Gen(source.self(), stride_);
792 * Sample - For taking a random sample of N elements from a sequence
793 * (without replacement).
795 template <class Random>
796 class Sample : public Operator<Sample<Random>> {
801 explicit Sample(size_t count, Random rng)
802 : count_(count), rng_(std::move(rng)) {}
804 template <class Value,
807 class StorageType = typename std::decay<Value>::type>
809 : public GenImpl<StorageType&&,
810 Generator<Value, Source, Rand, StorageType>> {
811 static_assert(!Source::infinite, "Cannot sample infinite source!");
812 // It's too easy to bite ourselves if random generator is only 16-bit
813 static_assert(Random::max() >= std::numeric_limits<int32_t>::max() - 1,
814 "Random number generator must support big values");
820 explicit Generator(Source source, size_t count, Random rng)
821 : source_(std::move(source)), count_(count), rng_(std::move(rng)) {}
823 template <class Handler>
824 bool apply(Handler&& handler) const {
828 std::vector<StorageType> v;
830 // use reservoir sampling to give each source value an equal chance
831 // of appearing in our output.
833 source_.foreach([&](Value value) -> void {
834 if (v.size() < count_) {
835 v.push_back(std::forward<Value>(value));
837 // alternatively, we could create a std::uniform_int_distribution
838 // instead of using modulus, but benchmarks show this has
839 // substantial overhead.
840 size_t index = rng_() % n;
841 if (index < v.size()) {
842 v[index] = std::forward<Value>(value);
848 // output is unsorted!
849 for (auto& val : v) {
850 if (!handler(std::move(val))) {
857 // Only takes N elements, so finite
858 static constexpr bool infinite = false;
861 template <class Source,
863 class Gen = Generator<Value, Source, Random>>
864 Gen compose(GenImpl<Value, Source>&& source) const {
865 return Gen(std::move(source.self()), count_, rng_);
868 template <class Source,
870 class Gen = Generator<Value, Source, Random>>
871 Gen compose(const GenImpl<Value, Source>& source) const {
872 return Gen(source.self(), count_, rng_);
877 * Skip - For skipping N items from the beginning of a source generator.
879 * This type is usually used through the 'skip' helper function, like:
881 * auto page = from(results)
882 * | skip(pageSize * startPage)
885 class Skip : public Operator<Skip> {
889 explicit Skip(size_t count) : count_(count) {}
891 template <class Value, class Source>
892 class Generator : public GenImpl<Value, Generator<Value, Source>> {
897 explicit Generator(Source source, size_t count)
898 : source_(std::move(source)), count_(count) {}
900 template <class Body>
901 void foreach(Body&& body) const {
903 source_.foreach(body);
907 source_.foreach([&](Value value) {
911 body(std::forward<Value>(value));
916 template <class Handler>
917 bool apply(Handler&& handler) const {
919 return source_.apply(std::forward<Handler>(handler));
922 return source_.apply([&](Value value) -> bool {
927 return handler(std::forward<Value>(value));
931 // Skipping N items of an infinite source is still infinite
932 static constexpr bool infinite = Source::infinite;
935 template <class Source,
937 class Gen = Generator<Value, Source>>
938 Gen compose(GenImpl<Value, Source>&& source) const {
939 return Gen(std::move(source.self()), count_);
942 template <class Source,
944 class Gen = Generator<Value, Source>>
945 Gen compose(const GenImpl<Value, Source>& source) const {
946 return Gen(source.self(), count_);
951 * Order - For ordering a sequence of values from a source by key.
952 * The key is extracted by the given selector functor, and this key is then
953 * compared using the specified comparator.
955 * This type is usually used through the 'order' helper function, like:
957 * auto closest = from(places)
958 * | orderBy([](Place& p) {
959 * return -distance(p.location, here);
963 template <class Selector, class Comparer>
964 class Order : public Operator<Order<Selector, Comparer>> {
971 explicit Order(Selector selector) : selector_(std::move(selector)) {}
973 Order(Selector selector, Comparer comparer)
974 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
976 template <class Value,
978 class StorageType = typename std::decay<Value>::type,
979 class Result = typename std::result_of<Selector(Value)>::type>
981 : public GenImpl<StorageType&&,
982 Generator<Value, Source, StorageType, Result>> {
983 static_assert(!Source::infinite, "Cannot sort infinite source!");
988 typedef std::vector<StorageType> VectorType;
990 VectorType asVector() const {
991 auto comparer = [&](const StorageType& a, const StorageType& b) {
992 return comparer_(selector_(a), selector_(b));
994 auto vals = source_ | as<VectorType>();
995 std::sort(vals.begin(), vals.end(), comparer);
996 return std::move(vals);
1000 Generator(Source source, Selector selector, Comparer comparer)
1001 : source_(std::move(source)),
1002 selector_(std::move(selector)),
1003 comparer_(std::move(comparer)) {}
1005 VectorType operator|(const Collect<VectorType>&) const {
1009 VectorType operator|(const CollectTemplate<std::vector>&) const {
1013 template <class Body>
1014 void foreach(Body&& body) const {
1015 for (auto& value : asVector()) {
1016 body(std::move(value));
1020 template <class Handler>
1021 bool apply(Handler&& handler) const {
1022 auto comparer = [&](const StorageType& a, const StorageType& b) {
1023 // swapped for minHeap
1024 return comparer_(selector_(b), selector_(a));
1026 auto heap = source_ | as<VectorType>();
1027 std::make_heap(heap.begin(), heap.end(), comparer);
1028 while (!heap.empty()) {
1029 std::pop_heap(heap.begin(), heap.end(), comparer);
1030 if (!handler(std::move(heap.back()))) {
1038 // Can only be run on and produce finite generators
1039 static constexpr bool infinite = false;
1042 template <class Source,
1044 class Gen = Generator<Value, Source>>
1045 Gen compose(GenImpl<Value, Source>&& source) const {
1046 return Gen(std::move(source.self()), selector_, comparer_);
1049 template <class Source,
1051 class Gen = Generator<Value, Source>>
1052 Gen compose(const GenImpl<Value, Source>& source) const {
1053 return Gen(source.self(), selector_, comparer_);
1058 * GroupBy - Group values by a given key selector, producing a sequence of
1061 * This type is usually used through the 'groupBy' helper function, like:
1065 * | groupBy([](const Place& p) {
1068 * | [](Group<std::string, Place>&& g) {
1069 * cout << g.key() << ": " << (g | first).description;
1072 template <class Selector>
1073 class GroupBy : public Operator<GroupBy<Selector>> {
1079 explicit GroupBy(Selector selector) : selector_(std::move(selector)) {}
1081 template <class Value,
1083 class ValueDecayed = typename std::decay<Value>::type,
1084 class Key = typename std::result_of<Selector(Value)>::type,
1085 class KeyDecayed = typename std::decay<Key>::type>
1088 Group<KeyDecayed, ValueDecayed>&&,
1089 Generator<Value, Source, ValueDecayed, Key, KeyDecayed>> {
1090 static_assert(!Source::infinite, "Cannot group infinite source!");
1095 Generator(Source source, Selector selector)
1096 : source_(std::move(source)), selector_(std::move(selector)) {}
1098 typedef Group<KeyDecayed, ValueDecayed> GroupType;
1100 template <class Handler>
1101 bool apply(Handler&& handler) const {
1102 std::unordered_map<KeyDecayed, typename GroupType::VectorType> groups;
1103 source_ | [&](Value value) {
1104 const Value& cv = value;
1105 auto& group = groups[selector_(cv)];
1106 group.push_back(std::forward<Value>(value));
1108 for (auto& kg : groups) {
1109 GroupType group(kg.first, std::move(kg.second));
1110 if (!handler(std::move(group))) {
1118 // Can only be run on and produce finite generators
1119 static constexpr bool infinite = false;
1122 template <class Source,
1124 class Gen = Generator<Value, Source>>
1125 Gen compose(GenImpl<Value, Source>&& source) const {
1126 return Gen(std::move(source.self()), selector_);
1129 template <class Source,
1131 class Gen = Generator<Value, Source>>
1132 Gen compose(const GenImpl<Value, Source>& source) const {
1133 return Gen(source.self(), selector_);
1138 * TypeAssertion - For verifying the exact type of the value produced by a
1139 * generator. Useful for testing and debugging, and acts as a no-op at runtime.
1140 * Pass-through at runtime. Used through the 'assert_type<>()' factory method
1143 * auto c = from(vector) | assert_type<int&>() | sum;
1146 template <class Expected>
1147 class TypeAssertion : public Operator<TypeAssertion<Expected>> {
1149 template <class Source, class Value>
1150 const Source& compose(const GenImpl<Value, Source>& source) const {
1151 static_assert(std::is_same<Expected, Value>::value,
1152 "assert_type() check failed");
1153 return source.self();
1156 template <class Source, class Value>
1157 Source&& compose(GenImpl<Value, Source>&& source) const {
1158 static_assert(std::is_same<Expected, Value>::value,
1159 "assert_type() check failed");
1160 return std::move(source.self());
1165 * Distinct - For filtering duplicates out of a sequence. A selector may be
1166 * provided to generate a key to uniquify for each value.
1168 * This type is usually used through the 'distinct' helper function, like:
1170 * auto closest = from(results)
1171 * | distinctBy([](Item& i) {
1176 template <class Selector>
1177 class Distinct : public Operator<Distinct<Selector>> {
1181 Distinct() = default;
1183 explicit Distinct(Selector selector) : selector_(std::move(selector)) {}
1185 template <class Value, class Source>
1186 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1190 typedef typename std::decay<Value>::type StorageType;
1192 // selector_ cannot be passed an rvalue or it would end up passing the husk
1193 // of a value to the downstream operators.
1194 typedef const StorageType& ParamType;
1196 typedef typename std::result_of<Selector(ParamType)>::type KeyType;
1197 typedef typename std::decay<KeyType>::type KeyStorageType;
1200 Generator(Source source, Selector selector)
1201 : source_(std::move(source)), selector_(std::move(selector)) {}
1203 template <class Body>
1204 void foreach(Body&& body) const {
1205 std::unordered_set<KeyStorageType> keysSeen;
1206 source_.foreach([&](Value value) {
1207 if (keysSeen.insert(selector_(ParamType(value))).second) {
1208 body(std::forward<Value>(value));
1213 template <class Handler>
1214 bool apply(Handler&& handler) const {
1215 std::unordered_set<KeyStorageType> keysSeen;
1216 return source_.apply([&](Value value) -> bool {
1217 if (keysSeen.insert(selector_(ParamType(value))).second) {
1218 return handler(std::forward<Value>(value));
1224 // While running distinct on an infinite sequence might produce a
1225 // conceptually finite sequence, it will take infinite time
1226 static constexpr bool infinite = Source::infinite;
1229 template <class Source,
1231 class Gen = Generator<Value, Source>>
1232 Gen compose(GenImpl<Value, Source>&& source) const {
1233 return Gen(std::move(source.self()), selector_);
1236 template <class Source,
1238 class Gen = Generator<Value, Source>>
1239 Gen compose(const GenImpl<Value, Source>& source) const {
1240 return Gen(source.self(), selector_);
1245 * Composer - Helper class for adapting pipelines into functors. Primarily used
1248 template <class Operators>
1253 explicit Composer(Operators op) : op_(std::move(op)) {}
1255 template <class Source,
1256 class Ret = decltype(
1257 std::declval<Operators>().compose(std::declval<Source>()))>
1258 Ret operator()(Source&& source) const {
1259 return op_.compose(std::forward<Source>(source));
1264 * Batch - For producing fixed-size batches of each value from a source.
1266 * This type is usually used through the 'batch' helper function:
1271 * | map([](const std::vector<int>& batch) {
1272 * return from(batch) | sum;
1276 class Batch : public Operator<Batch> {
1280 explicit Batch(size_t batchSize) : batchSize_(batchSize) {
1281 if (batchSize_ == 0) {
1282 throw std::invalid_argument("Batch size must be non-zero!");
1286 template <class Value,
1288 class StorageType = typename std::decay<Value>::type,
1289 class VectorType = std::vector<StorageType>>
1291 : public GenImpl<VectorType&,
1292 Generator<Value, Source, StorageType, VectorType>> {
1297 explicit Generator(Source source, size_t batchSize)
1298 : source_(std::move(source)), batchSize_(batchSize) {}
1300 template <class Handler>
1301 bool apply(Handler&& handler) const {
1303 batch_.reserve(batchSize_);
1304 bool shouldContinue = source_.apply([&](Value value) -> bool {
1305 batch_.push_back(std::forward<Value>(value));
1306 if (batch_.size() == batchSize_) {
1307 bool needMore = handler(batch_);
1311 // Always need more if the handler is not called.
1314 // Flush everything, if and only if `handler` hasn't returned false.
1315 if (shouldContinue && !batch_.empty()) {
1316 shouldContinue = handler(batch_);
1319 return shouldContinue;
1322 // Taking n-tuples of an infinite source is still infinite
1323 static constexpr bool infinite = Source::infinite;
1326 template <class Source,
1328 class Gen = Generator<Value, Source>>
1329 Gen compose(GenImpl<Value, Source>&& source) const {
1330 return Gen(std::move(source.self()), batchSize_);
1333 template <class Source,
1335 class Gen = Generator<Value, Source>>
1336 Gen compose(const GenImpl<Value, Source>& source) const {
1337 return Gen(source.self(), batchSize_);
1342 * Concat - For flattening generators of generators.
1344 * This type is usually used through the 'concat' static value, like:
1348 * | map([](Node& x) {
1349 * return from(x.neighbors)
1350 * | map([&](Node& y) {
1351 * return Edge(x, y);
1357 class Concat : public Operator<Concat> {
1361 template <class Inner,
1363 class InnerValue = typename std::decay<Inner>::type::ValueType>
1365 : public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1369 explicit Generator(Source source) : source_(std::move(source)) {}
1371 template <class Handler>
1372 bool apply(Handler&& handler) const {
1373 return source_.apply([&](Inner inner) -> bool {
1374 return inner.apply(std::forward<Handler>(handler));
1378 template <class Body>
1379 void foreach(Body&& body) const {
1380 source_.foreach([&](Inner inner) {
1381 inner.foreach(std::forward<Body>(body));
1385 // Resulting concatination is only finite if both Source and Inner are also
1386 // finite. In one sence, if dosn't make sence to call concat when the Inner
1387 // generator is infinite (you could just call first), so we could also just
1388 // static_assert if the inner is infinite. Taking the less restrictive
1390 static constexpr bool infinite =
1391 Source::infinite || std::decay<Inner>::type::infinite;
1394 template <class Value,
1396 class Gen = Generator<Value, Source>>
1397 Gen compose(GenImpl<Value, Source>&& source) const {
1398 return Gen(std::move(source.self()));
1401 template <class Value,
1403 class Gen = Generator<Value, Source>>
1404 Gen compose(const GenImpl<Value, Source>& source) const {
1405 return Gen(source.self());
1410 * RangeConcat - For flattening generators of iterables.
1412 * This type is usually used through the 'rconcat' static value, like:
1414 * map<int, vector<int>> adjacency;
1421 class RangeConcat : public Operator<RangeConcat> {
1423 RangeConcat() = default;
1425 template <class Range,
1427 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1429 : public GenImpl<InnerValue, Generator<Range, Source, InnerValue>> {
1433 explicit Generator(Source source) : source_(std::move(source)) {}
1435 template <class Body>
1436 void foreach(Body&& body) const {
1437 source_.foreach([&](Range range) {
1438 for (auto& value : range) {
1444 template <class Handler>
1445 bool apply(Handler&& handler) const {
1446 return source_.apply([&](Range range) -> bool {
1447 for (auto& value : range) {
1448 if (!handler(value)) {
1456 // This is similar to concat, except that the inner iterables all are finite
1457 // so the only thing that matters is that the source is infinite.
1458 static constexpr bool infinite = Source::infinite;
1461 template <class Value,
1463 class Gen = Generator<Value, Source>>
1464 Gen compose(GenImpl<Value, Source>&& source) const {
1465 return Gen(std::move(source.self()));
1468 template <class Value,
1470 class Gen = Generator<Value, Source>>
1471 Gen compose(const GenImpl<Value, Source>& source) const {
1472 return Gen(source.self());
1477 * GuardImpl - For handling exceptions from downstream computation. Requires the
1478 * type of exception to catch, and handler function to invoke in the event of
1479 * the exception. Note that the handler may:
1480 * 1) return true to continue processing the sequence
1481 * 2) return false to end the sequence immediately
1482 * 3) throw, to pass the exception to the next catch
1483 * The handler must match the signature 'bool(Exception&, Value)'.
1485 * This type is used through the `guard` helper, like so:
1488 * = byLine(STDIN_FILENO)
1489 * | guard<std::runtime_error>([](std::runtime_error& e,
1491 * LOG(ERROR) << sp << ": " << e.str();
1492 * return true; // continue processing subsequent lines
1497 * TODO(tjackson): Rename this back to Guard.
1499 template <class Exception, class ErrorHandler>
1500 class GuardImpl : public Operator<GuardImpl<Exception, ErrorHandler>> {
1501 ErrorHandler handler_;
1504 explicit GuardImpl(ErrorHandler handler) : handler_(std::move(handler)) {}
1506 template <class Value, class Source>
1507 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1509 ErrorHandler handler_;
1512 explicit Generator(Source source, ErrorHandler handler)
1513 : source_(std::move(source)), handler_(std::move(handler)) {}
1515 template <class Handler>
1516 bool apply(Handler&& handler) const {
1517 return source_.apply([&](Value value) -> bool {
1519 handler(std::forward<Value>(value));
1521 } catch (Exception& e) {
1522 return handler_(e, std::forward<Value>(value));
1527 // Just passes value though, length unaffected
1528 static constexpr bool infinite = Source::infinite;
1531 template <class Value,
1533 class Gen = Generator<Value, Source>>
1534 Gen compose(GenImpl<Value, Source>&& source) const {
1535 return Gen(std::move(source.self()), handler_);
1538 template <class Value,
1540 class Gen = Generator<Value, Source>>
1541 Gen compose(const GenImpl<Value, Source>& source) const {
1542 return Gen(source.self(), handler_);
1547 * Dereference - For dereferencing a sequence of pointers while filtering out
1550 * This type is usually used through the 'dereference' static value, like:
1552 * auto refs = from(ptrs) | dereference;
1554 class Dereference : public Operator<Dereference> {
1556 Dereference() = default;
1558 template <class Value,
1560 class Result = decltype(*std::declval<Value>())>
1561 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1565 explicit Generator(Source source) : source_(std::move(source)) {}
1567 template <class Body>
1568 void foreach(Body&& body) const {
1569 source_.foreach([&](Value value) {
1571 return body(*std::forward<Value>(value));
1576 template <class Handler>
1577 bool apply(Handler&& handler) const {
1578 return source_.apply([&](Value value) -> bool {
1580 return handler(*std::forward<Value>(value));
1586 // Just passes value though, length unaffected
1587 static constexpr bool infinite = Source::infinite;
1590 template <class Source,
1592 class Gen = Generator<Value, Source>>
1593 Gen compose(GenImpl<Value, Source>&& source) const {
1594 return Gen(std::move(source.self()));
1597 template <class Source,
1599 class Gen = Generator<Value, Source>>
1600 Gen compose(const GenImpl<Value, Source>& source) const {
1601 return Gen(source.self());
1606 * Indirect - For producing a sequence of the addresses of the values in the
1609 * This type is usually used through the 'indirect' static value, like:
1611 * auto ptrs = from(refs) | indirect;
1613 class Indirect : public Operator<Indirect> {
1615 Indirect() = default;
1617 template <class Value,
1619 class Result = typename std::remove_reference<Value>::type*>
1620 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1622 static_assert(!std::is_rvalue_reference<Value>::value,
1623 "Cannot use indirect on an rvalue");
1626 explicit Generator(Source source) : source_(std::move(source)) {}
1628 template <class Body>
1629 void foreach(Body&& body) const {
1630 source_.foreach([&](Value value) {
1631 return body(&std::forward<Value>(value));
1635 template <class Handler>
1636 bool apply(Handler&& handler) const {
1637 return source_.apply([&](Value value) -> bool {
1638 return handler(&std::forward<Value>(value));
1642 // Just passes value though, length unaffected
1643 static constexpr bool infinite = Source::infinite;
1646 template <class Source,
1648 class Gen = Generator<Value, Source>>
1649 Gen compose(GenImpl<Value, Source>&& source) const {
1650 return Gen(std::move(source.self()));
1653 template <class Source,
1655 class Gen = Generator<Value, Source>>
1656 Gen compose(const GenImpl<Value, Source>& source) const {
1657 return Gen(source.self());
1662 * Cycle - For repeating a sequence forever.
1664 * This type is usually used through the 'cycle' static value, like:
1671 * or in the finite case:
1673 * auto thrice = g | cycle(3);
1675 template <bool forever>
1676 class Cycle : public Operator<Cycle<forever>> {
1677 off_t limit_; // not used if forever == true
1681 explicit Cycle(off_t limit) : limit_(limit) {
1684 "Cycle limit constructor should not be used when forever == true.");
1687 template <class Value, class Source>
1688 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1693 explicit Generator(Source source, off_t limit)
1694 : source_(std::move(source)), limit_(limit) {}
1696 template <class Handler>
1697 bool apply(Handler&& handler) const {
1699 auto handler2 = [&](Value value) {
1700 cont = handler(std::forward<Value>(value));
1703 // Becomes an infinte loop if forever == true
1704 for (off_t count = 0; (forever || count != limit_); ++count) {
1706 source_.apply(handler2);
1714 // This is the hardest one to infer. If we are simply doing a finite cycle,
1715 // then (gen | cycle(n)) is infinite if and only if gen is infinite.
1716 // However, if we are doing an infinite cycle, (gen | cycle) is infinite
1717 // unless gen is empty. However, we will always mark (gen | cycle) as
1718 // infinite, because patterns such as (gen | cycle | count) can either take
1719 // on exactly one value, or infinite loop.
1720 static constexpr bool infinite = forever || Source::infinite;
1723 template <class Source,
1725 class Gen = Generator<Value, Source>>
1726 Gen compose(GenImpl<Value, Source>&& source) const {
1727 return Gen(std::move(source.self()), limit_);
1730 template <class Source,
1732 class Gen = Generator<Value, Source>>
1733 Gen compose(const GenImpl<Value, Source>& source) const {
1734 return Gen(source.self(), limit_);
1738 * Convenience function for finite cycles used like:
1740 * auto tripled = gen | cycle(3);
1742 Cycle<false> operator()(off_t limit) const { return Cycle<false>(limit); }
1746 ******************************* Sinks *****************************************
1750 * FoldLeft - Left-associative functional fold. For producing an aggregate value
1751 * from a seed and a folder function. Useful for custom aggregators on a
1754 * This type is primarily used through the 'foldl' helper method, like:
1756 * double movingAverage = from(values)
1757 * | foldl(0.0, [](double avg, double sample) {
1758 * return sample * 0.1 + avg * 0.9;
1761 template <class Seed, class Fold>
1762 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
1767 FoldLeft() = default;
1768 FoldLeft(Seed seed, Fold fold)
1769 : seed_(std::move(seed)), fold_(std::move(fold)) {}
1771 template <class Source, class Value>
1772 Seed compose(const GenImpl<Value, Source>& source) const {
1773 static_assert(!Source::infinite, "Cannot foldl infinite source");
1775 source | [&](Value v) {
1776 accum = fold_(std::move(accum), std::forward<Value>(v));
1783 * First - For finding the first value in a sequence.
1785 * This type is primarily used through the 'first' static value, like:
1787 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1789 class First : public Operator<First> {
1793 template <class Source,
1795 class StorageType = typename std::decay<Value>::type>
1796 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1797 Optional<StorageType> accum;
1798 source | [&](Value v) -> bool {
1799 accum = std::forward<Value>(v);
1807 * IsEmpty - a helper class for isEmpty and notEmpty
1809 * Essentially returns 'result' if the source is empty. Note that this cannot be
1810 * called on an infinite source, because then there is only one possible return
1814 * Used primarily through 'isEmpty' and 'notEmpty' static values
1816 * bool hasPrimes = g | filter(prime) | notEmpty;
1817 * bool lacksEvens = g | filter(even) | isEmpty;
1819 * Also used in the implementation of 'any' and 'all'
1821 template <bool emptyResult>
1822 class IsEmpty : public Operator<IsEmpty<emptyResult>> {
1824 IsEmpty() = default;
1826 template <class Source, class Value>
1827 bool compose(const GenImpl<Value, Source>& source) const {
1828 static_assert(!Source::infinite,
1829 "Cannot call 'all', 'any', 'isEmpty', or 'notEmpty' on "
1830 "infinite source. 'all' and 'isEmpty' will either return "
1831 "false or hang. 'any' or 'notEmpty' will either return true "
1833 bool ans = emptyResult;
1835 [&](Value /* v */) -> bool {
1844 * Reduce - Functional reduce, for recursively combining values from a source
1845 * using a reducer function until there is only one item left. Useful for
1846 * combining values when an empty sequence doesn't make sense.
1848 * This type is primarily used through the 'reduce' helper method, like:
1850 * sring longest = from(names)
1851 * | reduce([](string&& best, string& current) {
1852 * return best.size() >= current.size() ? best : current;
1855 template <class Reducer>
1856 class Reduce : public Operator<Reduce<Reducer>> {
1861 explicit Reduce(Reducer reducer) : reducer_(std::move(reducer)) {}
1863 template <class Source,
1865 class StorageType = typename std::decay<Value>::type>
1866 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1867 static_assert(!Source::infinite, "Cannot reduce infinite source");
1868 Optional<StorageType> accum;
1869 source | [&](Value v) {
1870 if (auto target = accum.get_pointer()) {
1871 *target = reducer_(std::move(*target), std::forward<Value>(v));
1873 accum = std::forward<Value>(v);
1881 * Count - for simply counting the items in a collection.
1883 * This type is usually used through its singleton, 'count':
1885 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1887 class Count : public Operator<Count> {
1891 template <class Source, class Value>
1892 size_t compose(const GenImpl<Value, Source>& source) const {
1893 static_assert(!Source::infinite, "Cannot count infinite source");
1894 return foldl(size_t(0),
1895 [](size_t accum, Value /* v */) { return accum + 1; })
1901 * Sum - For simply summing up all the values from a source.
1903 * This type is usually used through its singleton, 'sum':
1905 * auto gaussSum = seq(1, 100) | sum;
1907 class Sum : public Operator<Sum> {
1911 template <class Source,
1913 class StorageType = typename std::decay<Value>::type>
1914 StorageType compose(const GenImpl<Value, Source>& source) const {
1915 static_assert(!Source::infinite, "Cannot sum infinite source");
1916 return foldl(StorageType(0),
1917 [](StorageType&& accum, Value v) {
1918 return std::move(accum) + std::forward<Value>(v);
1924 * Contains - For testing whether a value matching the given value is contained
1927 * This type should be used through the 'contains' helper method, like:
1929 * bool contained = seq(1, 10) | map(square) | contains(49);
1931 template <class Needle>
1932 class Contains : public Operator<Contains<Needle>> {
1936 explicit Contains(Needle needle) : needle_(std::move(needle)) {}
1938 template <class Source,
1940 class StorageType = typename std::decay<Value>::type>
1941 bool compose(const GenImpl<Value, Source>& source) const {
1942 static_assert(!Source::infinite,
1943 "Calling contains on an infinite source might cause "
1944 "an infinite loop.");
1945 return !(source | [this](Value value) {
1946 return !(needle_ == std::forward<Value>(value));
1952 * Min - For a value which minimizes a key, where the key is determined by a
1953 * given selector, and compared by given comparer.
1955 * This type is usually used through the singletone 'min' or through the helper
1956 * functions 'minBy' and 'maxBy'.
1958 * auto oldest = from(people)
1959 * | minBy([](Person& p) {
1960 * return p.dateOfBirth;
1963 template <class Selector, class Comparer>
1964 class Min : public Operator<Min<Selector, Comparer>> {
1968 template <typename T>
1969 const T& asConst(const T& t) const {
1976 explicit Min(Selector selector) : selector_(std::move(selector)) {}
1978 Min(Selector selector, Comparer comparer)
1979 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
1981 template <class Value,
1983 class StorageType = typename std::decay<Value>::type,
1984 class Key = typename std::decay<
1985 typename std::result_of<Selector(Value)>::type>::type>
1986 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1987 static_assert(!Source::infinite,
1988 "Calling min or max on an infinite source will cause "
1989 "an infinite loop.");
1990 Optional<StorageType> min;
1991 Optional<Key> minKey;
1992 source | [&](Value v) {
1993 Key key = selector_(asConst(v)); // so that selector_ cannot mutate v
1994 if (auto lastKey = minKey.get_pointer()) {
1995 if (!comparer_(key, *lastKey)) {
1999 minKey = std::move(key);
2000 min = std::forward<Value>(v);
2007 * Append - For collecting values from a source into a given output container
2010 * This type is usually used through the helper function 'appendTo', like:
2012 * vector<int64_t> ids;
2013 * from(results) | map([](Person& p) { return p.id })
2016 template <class Collection>
2017 class Append : public Operator<Append<Collection>> {
2018 Collection* collection_;
2021 explicit Append(Collection* collection) : collection_(collection) {}
2023 template <class Value, class Source>
2024 Collection& compose(const GenImpl<Value, Source>& source) const {
2025 static_assert(!Source::infinite, "Cannot appendTo with infinite source");
2026 source | [&](Value v) {
2027 collection_->insert(collection_->end(), std::forward<Value>(v));
2029 return *collection_;
2034 * Collect - For collecting values from a source in a collection of the desired
2037 * This type is usually used through the helper function 'as', like:
2039 * std::string upper = from(stringPiece)
2041 * | as<std::string>();
2043 template <class Collection>
2044 class Collect : public Operator<Collect<Collection>> {
2046 Collect() = default;
2048 template <class Value,
2050 class StorageType = typename std::decay<Value>::type>
2051 Collection compose(const GenImpl<Value, Source>& source) const {
2052 static_assert(!Source::infinite,
2053 "Cannot convert infinite source to object with as.");
2054 Collection collection;
2055 source | [&](Value v) {
2056 collection.insert(collection.end(), std::forward<Value>(v));
2063 * CollectTemplate - For collecting values from a source in a collection
2064 * constructed using the specified template type. Given the type of values
2065 * produced by the given generator, the collection type will be:
2066 * Container<Value, Allocator<Value>>
2068 * The allocator defaults to std::allocator, so this may be used for the STL
2069 * containers by simply using operators like 'as<set>', 'as<deque>',
2070 * 'as<vector>'. 'as', here is the helper method which is the usual means of
2071 * constructing this operator.
2075 * set<string> uniqueNames = from(names) | as<set>();
2077 template <template <class, class> class Container,
2078 template <class> class Allocator>
2079 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
2081 CollectTemplate() = default;
2083 template <class Value,
2085 class StorageType = typename std::decay<Value>::type,
2086 class Collection = Container<StorageType, Allocator<StorageType>>>
2087 Collection compose(const GenImpl<Value, Source>& source) const {
2088 static_assert(!Source::infinite,
2089 "Cannot convert infinite source to object with as.");
2090 Collection collection;
2091 source | [&](Value v) {
2092 collection.insert(collection.end(), std::forward<Value>(v));
2099 * UnwrapOr - For unwrapping folly::Optional values, or providing the given
2100 * fallback value. Usually used through the 'unwrapOr' helper like so:
2102 * auto best = from(scores) | max | unwrapOr(-1);
2104 * Note that the fallback value needn't match the value in the Optional it is
2105 * unwrapping. If mis-matched types are supported, the common type of the two is
2106 * returned by value. If the types match, a reference (T&& > T& > const T&) is
2112 explicit UnwrapOr(T&& value) : value_(std::move(value)) {}
2113 explicit UnwrapOr(const T& value) : value_(value) {}
2115 T& value() { return value_; }
2116 const T& value() const { return value_; }
2123 T&& operator|(Optional<T>&& opt, UnwrapOr<T>&& fallback) {
2124 if (T* p = opt.get_pointer()) {
2125 return std::move(*p);
2127 return std::move(fallback.value());
2131 T& operator|(Optional<T>& opt, UnwrapOr<T>& fallback) {
2132 if (T* p = opt.get_pointer()) {
2135 return fallback.value();
2139 const T& operator|(const Optional<T>& opt, const UnwrapOr<T>& fallback) {
2140 if (const T* p = opt.get_pointer()) {
2143 return fallback.value();
2146 // Mixed type unwrapping always returns values, moving where possible
2149 class R = typename std::enable_if<
2150 !std::is_same<T, U>::value,
2151 typename std::common_type<T, U>::type>::type>
2152 R operator|(Optional<T>&& opt, UnwrapOr<U>&& fallback) {
2153 if (T* p = opt.get_pointer()) {
2154 return std::move(*p);
2156 return std::move(fallback.value());
2161 class R = typename std::enable_if<
2162 !std::is_same<T, U>::value,
2163 typename std::common_type<T, U>::type>::type>
2164 R operator|(const Optional<T>& opt, UnwrapOr<U>&& fallback) {
2165 if (const T* p = opt.get_pointer()) {
2168 return std::move(fallback.value());
2173 class R = typename std::enable_if<
2174 !std::is_same<T, U>::value,
2175 typename std::common_type<T, U>::type>::type>
2176 R operator|(Optional<T>&& opt, const UnwrapOr<U>& fallback) {
2177 if (T* p = opt.get_pointer()) {
2178 return std::move(*p);
2180 return fallback.value();
2185 class R = typename std::enable_if<
2186 !std::is_same<T, U>::value,
2187 typename std::common_type<T, U>::type>::type>
2188 R operator|(const Optional<T>& opt, const UnwrapOr<U>& fallback) {
2189 if (const T* p = opt.get_pointer()) {
2192 return fallback.value();
2196 * Unwrap - For unwrapping folly::Optional values in a folly::gen style. Usually
2197 * used through the 'unwrap' instace like so:
2199 * auto best = from(scores) | max | unwrap; // may throw
2204 T&& operator|(Optional<T>&& opt, const Unwrap&) {
2205 return std::move(opt.value());
2209 T& operator|(Optional<T>& opt, const Unwrap&) {
2214 const T& operator|(const Optional<T>& opt, const Unwrap&) {
2221 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
2223 template <class Value>
2224 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
2227 virtual ~WrapperBase() noexcept {}
2228 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
2229 virtual void foreach(const std::function<void(Value)>& body) const = 0;
2230 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
2233 template <class Wrapped>
2234 class WrapperImpl : public WrapperBase {
2238 explicit WrapperImpl(Wrapped wrapped) : wrapped_(std::move(wrapped)) {}
2240 bool apply(const std::function<bool(Value)>& handler) const override {
2241 return wrapped_.apply(handler);
2244 void foreach(const std::function<void(Value)>& body) const override {
2245 wrapped_.foreach(body);
2248 std::unique_ptr<const WrapperBase> clone() const override {
2249 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
2253 std::unique_ptr<const WrapperBase> wrapper_;
2256 template <class Self>
2257 /* implicit */ VirtualGen(Self source)
2258 : wrapper_(new WrapperImpl<Self>(std::move(source))) {}
2260 VirtualGen(VirtualGen&& source) noexcept
2261 : wrapper_(std::move(source.wrapper_)) {}
2263 VirtualGen(const VirtualGen& source) : wrapper_(source.wrapper_->clone()) {}
2265 VirtualGen& operator=(const VirtualGen& source) {
2266 wrapper_.reset(source.wrapper_->clone());
2270 VirtualGen& operator=(VirtualGen&& source) noexcept {
2271 wrapper_ = std::move(source.wrapper_);
2275 bool apply(const std::function<bool(Value)>& handler) const {
2276 return wrapper_->apply(handler);
2279 void foreach(const std::function<void(Value)>& body) const {
2280 wrapper_->foreach(body);
2285 * non-template operators, statically defined to avoid the need for anything but
2288 constexpr detail::Sum sum{};
2290 constexpr detail::Count count{};
2292 constexpr detail::First first{};
2294 constexpr detail::IsEmpty<true> isEmpty{};
2296 constexpr detail::IsEmpty<false> notEmpty{};
2298 constexpr detail::Min<Identity, Less> min{};
2300 constexpr detail::Min<Identity, Greater> max{};
2302 constexpr detail::Order<Identity> order{};
2304 constexpr detail::Distinct<Identity> distinct{};
2306 constexpr detail::Map<Move> move{};
2308 constexpr detail::Concat concat{};
2310 constexpr detail::RangeConcat rconcat{};
2312 constexpr detail::Cycle<true> cycle{};
2314 constexpr detail::Dereference dereference{};
2316 constexpr detail::Indirect indirect{};
2318 constexpr detail::Unwrap unwrap{};
2320 template <class Number>
2321 inline detail::Take take(Number count) {
2323 throw std::invalid_argument("Negative value passed to take()");
2325 return detail::Take(static_cast<size_t>(count));
2328 inline detail::Stride stride(size_t s) { return detail::Stride(s); }
2330 template <class Random = std::default_random_engine>
2331 inline detail::Sample<Random> sample(size_t count, Random rng = Random()) {
2332 return detail::Sample<Random>(count, std::move(rng));
2335 inline detail::Skip skip(size_t count) { return detail::Skip(count); }
2337 inline detail::Batch batch(size_t batchSize) {
2338 return detail::Batch(batchSize);
2343 #pragma GCC diagnostic pop