#ifndef ITER_REPEAT_HPP_ #define ITER_REPEAT_HPP_ #include #include #include namespace iter { namespace impl { template class RepeaterWithCount; } template constexpr impl::RepeaterWithCount repeat(T&&, int); } template class iter::impl::RepeaterWithCount { // see stackoverflow.com/questions/32174186/ about why this isn't // declaring just a specialization as friend template friend constexpr RepeaterWithCount iter::repeat(U&&, int); private: T elem; int count; constexpr RepeaterWithCount(T e, int c) : elem(std::forward(e)), count{c} {} using TPlain = typename std::remove_reference::type; public: RepeaterWithCount(RepeaterWithCount&&) = default; class Iterator : public std::iterator { private: const TPlain* elem; int count; public: constexpr Iterator(const TPlain* e, int c) : elem{e}, count{c} {} Iterator& operator++() { --this->count; return *this; } Iterator operator++(int) { auto ret = *this; ++*this; return ret; } constexpr bool operator!=(const Iterator& other) const { return !(*this == other); } constexpr bool operator==(const Iterator& other) const { return this->count == other.count; } constexpr const TPlain& operator*() const { return *this->elem; } constexpr const TPlain* operator->() const { return this->elem; } }; constexpr Iterator begin() const { return {&this->elem, this->count}; } constexpr Iterator end() const { return {&this->elem, 0}; } }; template constexpr iter::impl::RepeaterWithCount iter::repeat(T&& e, int count) { return {std::forward(e), count < 0 ? 0 : count}; } namespace iter { namespace impl { template class Repeater; } template constexpr impl::Repeater repeat(T&&); } template class iter::impl::Repeater { template friend constexpr Repeater iter::repeat(U&&); private: using TPlain = typename std::remove_reference::type; T elem; constexpr Repeater(T e) : elem(std::forward(e)) {} public: Repeater(Repeater&&) = default; class Iterator : public std::iterator { private: const TPlain* elem; public: constexpr Iterator(const TPlain* e) : elem{e} {} constexpr const Iterator& operator++() const { return *this; } constexpr Iterator operator++(int) const { return *this; } constexpr bool operator!=(const Iterator&) const { return true; } constexpr bool operator==(const Iterator&) const { return false; } constexpr const TPlain& operator*() const { return *this->elem; } constexpr const TPlain* operator->() const { return this->elem; } }; constexpr Iterator begin() const { return {&this->elem}; } constexpr Iterator end() const { return {nullptr}; } }; template constexpr iter::impl::Repeater iter::repeat(T&& e) { return {std::forward(e)}; } #endif