Last active
July 14, 2019 02:34
-
-
Save Sam-Belliveau/a10a2a4d61d53aaaeeed023b42defd54 to your computer and use it in GitHub Desktop.
C++ Range Library
This file contains hidden or 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
| /*\ | |
| |*| Copyright 2018, Sam R. Belliveau | |
| |*| | |
| |*| Permission is hereby granted, free of charge, to any person obtaining a copy | |
| |*| of this software and associated documentation files (the "Software"), to deal | |
| |*| in the Software without restriction, including without limitation the rights | |
| |*| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| |*| copies of the Software, and to permit persons to whom the Software is | |
| |*| furnished to do so, subject to the following conditions: | |
| |*| | |
| |*| The above copyright notice and this permission notice shall be | |
| |*| included in all copies or substantial portions of the Software. | |
| |*| UNLESS: the author has authorized it to be published in a library. | |
| |*| | |
| |*| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| |*| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| |*| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| |*| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| |*| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| |*| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| |*| SOFTWARE. | |
| \*/ | |
| #ifndef SAMS_RANGE_CONTAINER_CLASS_HPP | |
| #define SAMS_RANGE_CONTAINER_CLASS_HPP 1 | |
| #define SCL_RANGE_VER 200L | |
| #ifndef SCL_RANGE_CONSTEXPR | |
| #define SCL_FUNC_PREFIX inline | |
| #else | |
| #define SCL_FUNC_PREFIX inline constexpr | |
| #endif | |
| #include <iterator> // std::distance, std::iterator_traits, std::begin, std::end | |
| #ifndef SCL_RANGE_NO_PRINT | |
| #include <ostream> // std::ostream | |
| #endif | |
| namespace SCL { // Sam's Container Library | |
| template<class Iterator> | |
| struct Range | |
| { | |
| private: // Iterator Traits | |
| /* Short Hand for iterator_traits */ | |
| using Traits = std::iterator_traits<Iterator>; | |
| public: // Iterator Tags | |
| using difference_type = typename Traits::difference_type; | |
| using value_type = typename Traits::value_type; | |
| using iterator = Iterator; | |
| using const_iterator = const iterator; | |
| using reverse_iterator = std::reverse_iterator<iterator>; | |
| using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
| using reference = typename Traits::reference; | |
| using const_reference = const reference; | |
| private: // Members | |
| iterator first_, last_; | |
| public: // Constructors | |
| SCL_FUNC_PREFIX Range(iterator first, iterator last) : first_{first}, last_{last} {} | |
| SCL_FUNC_PREFIX Range(const Range &other) : first_{other.first_}, last_{other.last_} {} | |
| template<class Container> | |
| SCL_FUNC_PREFIX Range(Container& range) | |
| : first_{std::begin(range)}, last_{std::end(range)} {} | |
| template<class Container> | |
| SCL_FUNC_PREFIX Range(const Container& range) | |
| : first_{std::begin(range)}, last_{std::end(range)} {} | |
| public: // Iterators | |
| /* Iterators are passed by reference to */ | |
| /* Emulate passing an first and last iter */ | |
| SCL_FUNC_PREFIX iterator begin() const noexcept { return first_; } | |
| SCL_FUNC_PREFIX const_iterator cbegin() const noexcept { return first_; } | |
| SCL_FUNC_PREFIX iterator end() const noexcept { return last_; } | |
| SCL_FUNC_PREFIX const_iterator cend() const noexcept { return last_; } | |
| SCL_FUNC_PREFIX reverse_iterator rbegin() const noexcept { return last_; } | |
| SCL_FUNC_PREFIX const_reverse_iterator crbegin() const noexcept { return last_; } | |
| SCL_FUNC_PREFIX reverse_iterator rend() const noexcept { return first_; } | |
| SCL_FUNC_PREFIX const_reverse_iterator crend() const noexcept { return first_; } | |
| public: // Element Access [RANDOM ACCESS ONLY] | |
| SCL_FUNC_PREFIX reference operator[](std::size_t n) noexcept { return first_[n]; } | |
| SCL_FUNC_PREFIX reference operator()(std::size_t n) noexcept { return first_[n]; } | |
| SCL_FUNC_PREFIX const_reference operator[](std::size_t n) const noexcept { return first_[n]; } | |
| SCL_FUNC_PREFIX const_reference operator()(std::size_t n) const noexcept { return first_[n]; } | |
| SCL_FUNC_PREFIX reference first() noexcept { return *begin(); } | |
| SCL_FUNC_PREFIX const_reference first() const noexcept { return *begin(); } | |
| SCL_FUNC_PREFIX reference last() noexcept{ return *(end()-1); } | |
| SCL_FUNC_PREFIX const_reference last() const noexcept { return *(end()-1); } | |
| public: // Sub Ranges [RANDOM ACCESS ONLY] | |
| SCL_FUNC_PREFIX Range first(difference_type n) { return Range(begin(), begin() + n); } | |
| SCL_FUNC_PREFIX Range last(difference_type n) { return Range(end() - n, end()); } | |
| SCL_FUNC_PREFIX Range subrange(difference_type first, difference_type last) | |
| { return Range(begin() + first, begin() + last); } | |
| public: // Observers | |
| SCL_FUNC_PREFIX difference_type size() const noexcept { return std::distance(first_, last_); } | |
| SCL_FUNC_PREFIX difference_type empty() const noexcept { return first_ == last_; } | |
| #ifndef SCL_RANGE_NO_PRINT | |
| public: // OStream support | |
| SCL_FUNC_PREFIX friend std::ostream& operator<<(std::ostream& o, const Range& in) | |
| { | |
| o << "[" << in[0]; | |
| for(iterator i = 1 + in.cbegin(); i < in.cend(); ++i) | |
| o << ", " << *i; | |
| o << ']'; | |
| return o; | |
| } | |
| #endif | |
| }; | |
| namespace Iterator { | |
| template<class Container> | |
| struct Get { using Iterator = typename Container::iterator; }; | |
| template<class Container> | |
| struct Get<const Container> | |
| { using Iterator = typename Container::const_iterator; }; | |
| template<class T, std::size_t N> | |
| struct Get<T[N]> { using Iterator = T*; }; | |
| template<class T, std::size_t N> | |
| struct Get<const T[N]> { using Iterator = const T*; }; | |
| } | |
| #ifndef SCL_RANGE_NO_TEMPLATE_DEDUCTION | |
| #if __cplusplus >= 201703L /* C++17 Feature */ | |
| template<class Container> /* Template Deduction Guide */ | |
| Range(Container&) -> Range<typename Iterator::Get<Container>::Iterator>; | |
| #endif | |
| #endif | |
| /* C++11 Support That Doesnt Support Template Deduction Guides*/ | |
| template<class Container> | |
| Range<typename Iterator::Get<Container>::Iterator> MakeRange(Container& range) | |
| { return Range<typename Iterator::Get<Container>::Iterator>(range); } | |
| #undef SCL_FUNC_PREFIX | |
| } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment