Last active
October 17, 2017 06:28
-
-
Save HertzDevil/9c250a8ac2950a4cd5e21b36ebdda741 to your computer and use it in GitHub Desktop.
proj_for
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
| #include <iostream> | |
| #include <memory> | |
| #include <vector> | |
| #include <utility> | |
| #include <type_traits> | |
| namespace details { | |
| template <typename T> | |
| constexpr auto begin_expr(T&& x) { | |
| using std::begin; | |
| return begin(std::forward<T>(x)); | |
| } | |
| template <typename T> | |
| constexpr auto end_expr(T&& x) { | |
| using std::end; | |
| return end(std::forward<T>(x)); | |
| } | |
| template <typename T, typename F> | |
| struct begin_iterator { | |
| decltype(begin_expr(std::declval<T>())) it_; | |
| F f_; | |
| decltype(auto) operator*() { | |
| return f_(*it_); | |
| } | |
| begin_iterator &operator++() { | |
| ++it_; | |
| return *this; | |
| } | |
| }; | |
| template <typename T, typename F> | |
| struct end_iterator { | |
| decltype(end_expr(std::declval<T>())) it_; | |
| F f_; | |
| decltype(auto) operator*() { | |
| return f_(*it_); | |
| } | |
| end_iterator &operator++() { | |
| ++it_; | |
| return *this; | |
| } | |
| }; | |
| template <typename T, typename F> | |
| bool operator!=(const begin_iterator<T, F> &b, const end_iterator<T, F> &e) { | |
| return b.it_ != e.it_; | |
| } | |
| } // namespace details | |
| template <typename T, typename F> | |
| struct proj_t { | |
| proj_t(T&& x, F&& f) : | |
| x_(std::forward<T>(x)), | |
| b_ {details::begin_expr(x_), std::forward<F>(f)}, | |
| e_ {details::end_expr(x_), std::forward<F>(f)} | |
| { | |
| } | |
| auto begin() { | |
| return b_; | |
| } | |
| auto end() { | |
| return e_; | |
| } | |
| private: | |
| T x_; | |
| details::begin_iterator<T&&, F> b_; | |
| details::end_iterator<T&&, F> e_; | |
| }; | |
| template <typename T, typename F> | |
| auto proj(T&& x, F&& f) { | |
| return proj_t<T, F>(std::forward<T>(x), std::forward<F>(f)); | |
| } | |
| template <typename T> | |
| auto proj_deref(T&& x) { | |
| return proj(std::forward<T>(x), [] (const auto &x) -> decltype(auto) { return *x; }); | |
| } | |
| int main() { | |
| std::vector<std::unique_ptr<int>> v; | |
| v.push_back(std::make_unique<int>(3)); | |
| v.push_back(std::make_unique<int>(7)); | |
| v.push_back(std::make_unique<int>(5)); | |
| for (auto& x : proj_deref(v)) | |
| std::cout << x << '\n'; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment