Skip to content

Instantly share code, notes, and snippets.

@HertzDevil
Last active October 17, 2017 06:28
Show Gist options
  • Select an option

  • Save HertzDevil/9c250a8ac2950a4cd5e21b36ebdda741 to your computer and use it in GitHub Desktop.

Select an option

Save HertzDevil/9c250a8ac2950a4cd5e21b36ebdda741 to your computer and use it in GitHub Desktop.
proj_for
#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