Created
September 26, 2019 21:24
-
-
Save eklitzke/54091655d97eb22f3def0c304255731d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // A sample standard C++20 program that prints | |
| // the first N Pythagorean triples. | |
| #include <iostream> | |
| #include <optional> | |
| #include <ranges> // New header! | |
| using namespace std; | |
| // maybe_view defines a view over zero or one | |
| // objects. | |
| template<Semiregular T> | |
| struct maybe_view : view_interface<maybe_view<T>> { | |
| maybe_view() = default; | |
| maybe_view(T t) : data_(std::move(t)) { | |
| } | |
| T const *begin() const noexcept { | |
| return data_ ? &*data_ : nullptr; | |
| } | |
| T const *end() const noexcept { | |
| return data_ ? &*data_ + 1 : nullptr; | |
| } | |
| private: | |
| optional<T> data_{}; | |
| }; | |
| // "for_each" creates a new view by applying a | |
| // transformation to each element in an input | |
| // range, and flattening the resulting range of | |
| // ranges. | |
| // (This uses one syntax for constrained lambdas | |
| // in C++20.) | |
| inline constexpr auto for_each = | |
| []<Range R, | |
| Iterator I = iterator_t<R>, | |
| IndirectUnaryInvocable<I> Fun>(R&& r, Fun fun) | |
| requires Range<indirect_result_t<Fun, I>> { | |
| return std::forward<R>(r) | |
| | view::transform(std::move(fun)) | |
| | view::join; | |
| }; | |
| // "yield_if" takes a bool and a value and | |
| // returns a view of zero or one elements. | |
| inline constexpr auto yield_if = | |
| []<Semiregular T>(bool b, T x) { | |
| return b ? maybe_view{std::move(x)} | |
| : maybe_view<T>{}; | |
| }; | |
| int main() { | |
| // Define an infinite range of all the | |
| // Pythagorean triples: | |
| using view::iota; | |
| auto triples = | |
| for_each(iota(1), [](int z) { | |
| return for_each(iota(1, z+1), [=](int x) { | |
| return for_each(iota(x, z+1), [=](int y) { | |
| return yield_if(x*x + y*y == z*z, | |
| make_tuple(x, y, z)); | |
| }); | |
| }); | |
| }); | |
| // Display the first 10 triples | |
| for(auto triple : triples | view::take(10)) { | |
| cout << '(' | |
| << get<0>(triple) << ',' | |
| << get<1>(triple) << ',' | |
| << get<2>(triple) << ')' << '\n'; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment