forked from OSchip/llvm-project
151 lines
4.1 KiB
C++
151 lines
4.1 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
|
|
|
|
namespace value_range_detail {
|
|
template<typename T>
|
|
class value_range_iter {
|
|
T t;
|
|
public:
|
|
value_range_iter(const T &t) : t(t) {}
|
|
T operator*() const { return t; }
|
|
bool operator!=(const value_range_iter &o) const { return t != o.t; }
|
|
value_range_iter &operator++() { ++t; return *this; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct value_range {
|
|
value_range(const T &a, const T &b) : begin_(a), end_(b) {}
|
|
value_range_iter<T> begin_, end_;
|
|
};
|
|
|
|
template<typename T>
|
|
value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; }
|
|
template<typename T>
|
|
value_range_iter<T> end(const value_range<T> &r) { return r.end_; }
|
|
|
|
|
|
struct end_t {};
|
|
|
|
template<typename T>
|
|
class value_range_step_iter {
|
|
T it, step;
|
|
public:
|
|
value_range_step_iter(const T &it, const T &step) : it(it), step(step) {}
|
|
T operator*() const { return it; }
|
|
bool operator!=(value_range_step_iter end) const { return it != end.it; }
|
|
value_range_step_iter &operator++() { it += step; return *this; }
|
|
};
|
|
|
|
template<typename T>
|
|
class value_range_step {
|
|
T it, step, end_;
|
|
public:
|
|
value_range_step(const T &it, const T &end, const T &step) :
|
|
it(it), end_(end), step(step) {}
|
|
typedef value_range_step_iter<T> iterator;
|
|
iterator begin() const { return iterator(it, step); }
|
|
iterator end() const { return iterator(end_, step); }
|
|
};
|
|
}
|
|
|
|
template<typename T>
|
|
value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); }
|
|
|
|
template<typename T>
|
|
value_range_detail::value_range_step<T> range(const T &a, const T &b, const T &step) { return value_range_detail::value_range_step<T>(a, b, step); }
|
|
|
|
|
|
namespace map_range {
|
|
template<typename T>
|
|
class vector {
|
|
T storage[100];
|
|
decltype(sizeof(char)) size;
|
|
public:
|
|
vector() : size() {}
|
|
void push_back(T t) { storage[size++] = t; }
|
|
T *begin() { return storage; }
|
|
T *end() { return storage + size; }
|
|
};
|
|
|
|
template<typename T> struct tuple_elem {
|
|
T t;
|
|
tuple_elem() {}
|
|
tuple_elem(T t) : t(t) {}
|
|
};
|
|
template<typename... A>
|
|
struct tuple : tuple_elem<A>... {
|
|
tuple() : tuple_elem<A>()... {}
|
|
tuple(A... a) : tuple_elem<A>(a)... {}
|
|
template<typename B> B &get() { return tuple_elem<B>::t; }
|
|
};
|
|
|
|
template<typename F, typename I>
|
|
class map_iter {
|
|
F f;
|
|
I i;
|
|
public:
|
|
map_iter(F f, I i) : f(f), i(i) {}
|
|
auto operator*() const -> decltype(f(*i)) { return f(*i); }
|
|
bool operator!=(const map_iter &o) const { return i != o.i; }
|
|
map_iter &operator++() { ++i; return *this; }
|
|
};
|
|
|
|
template<typename T>
|
|
struct iter_pair {
|
|
T begin_, end_;
|
|
iter_pair(T begin, T end) : begin_(begin), end_(end) {}
|
|
};
|
|
template<typename T> T begin(iter_pair<T> p) { return p.begin_; }
|
|
template<typename T> T end(iter_pair<T> p) { return p.end_; }
|
|
|
|
template<typename...> class mem_fun_impl;
|
|
template<typename R, typename T, typename... A>
|
|
class mem_fun_impl<R (T::*)(A...)> {
|
|
typedef R (T::*F)(A...);
|
|
F f;
|
|
public:
|
|
mem_fun_impl(F f) : f(f) {}
|
|
R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); }
|
|
};
|
|
template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); }
|
|
|
|
template<typename F, typename T>
|
|
auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> {
|
|
typedef map_iter<F, decltype(t.begin())> iter;
|
|
return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end()));
|
|
}
|
|
}
|
|
|
|
#define assert(b) if (!b) { return 1; }
|
|
int main() {
|
|
int total = 0;
|
|
|
|
for (auto n : range(1, 5)) {
|
|
total += n;
|
|
}
|
|
assert(total == 10);
|
|
|
|
for (auto n : range(10, 100, 10)) {
|
|
total += n;
|
|
}
|
|
assert(total == 460);
|
|
|
|
map_range::vector<char> chars;
|
|
chars.push_back('a');
|
|
chars.push_back('b');
|
|
chars.push_back('c');
|
|
for (char c : chars) {
|
|
++total;
|
|
}
|
|
assert(total == 463);
|
|
|
|
typedef map_range::tuple<int, double> T;
|
|
map_range::vector<T> pairs;
|
|
pairs.push_back(T(42, 12.9));
|
|
pairs.push_back(T(6, 4.2));
|
|
pairs.push_back(T(9, 1.1));
|
|
for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) {
|
|
total += a;
|
|
}
|
|
assert(total == 500);
|
|
}
|