Last active
June 6, 2018 12:34
-
-
Save yumetodo/b0f82fc44e0e4d842c45f7596a6a0b49 to your computer and use it in GitHub Desktop.
イテレーターをラップしてイテレータを作る練習
This file contains 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 <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; | |
} |
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
イテレータの解説をするなんて今更佳代 - Qiita