Skip to content

Instantly share code, notes, and snippets.

@yumetodo
Last active June 6, 2018 12:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yumetodo/b0f82fc44e0e4d842c45f7596a6a0b49 to your computer and use it in GitHub Desktop.
Save yumetodo/b0f82fc44e0e4d842c45f7596a6a0b49 to your computer and use it in GitHub Desktop.
イテレーターをラップしてイテレータを作る練習
#include <iterator>
#include <vector>
#include <iostream>
#include <utility>
struct Vec2f{
float x; float y;
};
struct Circle {
Vec2f pos;
float size;
};
template<typename Iterator, std::enable_if_t<std::is_same<Circle, typename std::iterator_traits<Iterator>::value_type>::value, std::nullptr_t> = nullptr>
class circle_pos_iterator
#if __cplusplus < 201500 //C++17ではstd::iteratorは消える
: std::iterator<typename std::iterator_traits<Iterator>::iterator_category, Vec2f>
#endif
{
private:
using ref_iterator_type = Iterator;
ref_iterator_type it_;
#if __cplusplus < 201500
using base_type = std::iterator<typename std::iterator_traits<Iterator>::iterator_category, Vec2f>;
#endif
public:
circle_pos_iterator() = default;
circle_pos_iterator(Iterator it) noexcept : it_(it) {}
circle_pos_iterator(const circle_pos_iterator&) = default;
circle_pos_iterator(circle_pos_iterator&&) = default;
circle_pos_iterator& operator=(const circle_pos_iterator&) = default;
circle_pos_iterator& operator=(circle_pos_iterator&&) = default;
ref_iterator_type get_raw_iterator() const { return it_; }
#if __cplusplus < 201500
using iterator_category = typename base_type::iterator_category;
using value_type = typename base_type::value_type;
using difference_type = typename base_type::difference_type;
using pointer = typename base_type::pointer;
using reference = typename base_type::reference;
#else
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using value_type = Vec2f;
using difference_type = std::ptrdiff_t;
using pointer = Vec2f*;
using reference = Vec2f&;
#endif
Vec2f& operator*() noexcept { return it_->pos; }
Vec2f operator*() const noexcept { return it_->pos; }
template<std::enable_if_t<std::is_base_of<std::input_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
Vec2f* operator->() noexcept { return &it_->pos; }
template<std::enable_if_t<std::is_base_of<std::input_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
const Vec2f* operator->() const noexcept { return &it_->pos; }
circle_pos_iterator& operator++() noexcept{
++this->it_;
return *this;
}
circle_pos_iterator operator++(int) noexcept{
const auto tmp = *this;
++*this;
return tmp;
}
template<std::enable_if_t<std::is_base_of<std::bidirectional_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator& operator--() noexcept{
--this->it_;
return *this;
}
template<std::enable_if_t<std::is_base_of<std::bidirectional_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator operator--(int) noexcept{
const auto tmp = *this;
--*this;
return tmp;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator operator+(difference_type r){
auto tmp = *this;
tmp.it_ += r;
return tmp;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator operator-(difference_type r){
auto tmp = *this;
tmp.it_ -= r;
return tmp;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator& operator+=(difference_type r){
this->it_ += r;
return *this;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
circle_pos_iterator& operator-=(difference_type r){
this->it_ -= r;
return *this;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
Vec2f* operator[](difference_type n) {
return this->it_[n].pos;
}
template<std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, iterator_category>::value, std::nullptr_t> = nullptr>
const Vec2f* operator[](difference_type n) const{
return this->it_[n].pos;
}
};
template<typename It, std::enable_if_t<std::is_base_of<std::input_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator==(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return l.get_raw_iterator() == r.get_raw_iterator(); }
template<typename It, std::enable_if_t<std::is_base_of<std::input_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator!=(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return !(l == r); }
template<typename It, std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator<(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return l.get_raw_iterator() < r.get_raw_iterator(); }
template<typename It, std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator>(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return l.get_raw_iterator() > r.get_raw_iterator(); }
template<typename It, std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator<=(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return l.get_raw_iterator() <= r.get_raw_iterator(); }
template<typename It, std::enable_if_t<std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value, std::nullptr_t> = nullptr>
bool operator>=(const circle_pos_iterator<It>& l, const circle_pos_iterator<It>& r){ return l.get_raw_iterator() >= r.get_raw_iterator(); }
template<typename It>
class circle_pos_iterator_range{
public:
using iterator = circle_pos_iterator<It>;
private:
iterator begin_; iterator end_;
public:
circle_pos_iterator_range() = delete;
circle_pos_iterator_range(It begin, It end) : begin_(begin), end_(end) {}
circle_pos_iterator_range(const circle_pos_iterator_range&) = default;
circle_pos_iterator_range(circle_pos_iterator_range&&) = default;
circle_pos_iterator_range& operator=(const circle_pos_iterator_range&) = default;
circle_pos_iterator_range& operator=(circle_pos_iterator_range&&) = default;
iterator& begin() noexcept { return this->begin_; }
const iterator& begin() const noexcept { return this->begin_; }
iterator& end() noexcept { return this->end_; }
const iterator& end() const noexcept { return this->end_; }
};
template<typename It, std::enable_if_t<std::is_same<Circle, typename std::iterator_traits<It>::value_type>::value, std::nullptr_t> = nullptr>
circle_pos_iterator_range<It> make_circle_pos_iterator_range(It begin, It end){
return {begin, end};
}
template<typename Container>
circle_pos_iterator_range<typename Container::iterator> make_circle_pos_iterator_range(Container c)
{
return make_circle_pos_iterator_range(c.begin(), c.end());
}
template<std::size_t N>
circle_pos_iterator_range<Circle*> make_circle_pos_iterator_range(Circle (&arr)[N]){
return make_circle_pos_iterator_range(std::begin(arr), std::end(arr));
}
int main(void){
std::vector<Circle> v(10);
Circle arr[10] = {};
for(auto&& p : make_circle_pos_iterator_range(v)){
std::cout << p.x << p.y << std::endl;
}
for(auto&& p : make_circle_pos_iterator_range(arr)){
std::cout << p.x << p.y << std::endl;
}
return 0;
}
@yumetodo
Copy link
Author

@yumetodo
Copy link
Author

Vec2f and Circle class was ported from openFrameworks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment