Skip to content

Instantly share code, notes, and snippets.

@Sam-Belliveau
Last active July 14, 2019 02:34
Show Gist options
  • Select an option

  • Save Sam-Belliveau/a10a2a4d61d53aaaeeed023b42defd54 to your computer and use it in GitHub Desktop.

Select an option

Save Sam-Belliveau/a10a2a4d61d53aaaeeed023b42defd54 to your computer and use it in GitHub Desktop.
C++ Range Library
/*\
|*| 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