Skip to content

Commit

Permalink
Introducing the ViewBase class
Browse files Browse the repository at this point in the history
  • Loading branch information
whaeck committed Nov 1, 2023
1 parent 5ed53f0 commit 1a050d1
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 80 deletions.
94 changes: 14 additions & 80 deletions src/tools/ranges/IteratorView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdexcept>

// other includes
#include "tools/ranges/ViewBase.hpp"

namespace njoy {
namespace tools {
Expand All @@ -17,11 +18,14 @@ namespace ranges {
*
* Currently only defined for random access iterators.
*/
template < class Iterator,
template < typename Iterator,
std::enable_if_t<
std::is_same< typename std::iterator_traits< Iterator >::iterator_category,
std::random_access_iterator_tag >::value, bool > = true >
class IteratorView {
class IteratorView : public ViewBase< IteratorView< Iterator > > {

/* type aliases */
using Parent = ViewBase< IteratorView< Iterator > >;

public:

Expand Down Expand Up @@ -69,84 +73,14 @@ class IteratorView {
*/
constexpr iterator end() const noexcept { return end_; }

/**
* @brief Return the reference to the front element of the view
*/
constexpr decltype(auto) front() const noexcept {

return *( this->begin() );
}

/**
* @brief Return the reference to the back element of the view
*/
constexpr decltype(auto) back() const noexcept {

return *( std::prev( this->end() ) );
}

/**
* @brief Return whether or not the view is empty
*/
constexpr bool empty() const noexcept { return this->begin() == this->end(); }

/**
* @brief Return the size of the iterator view
*/
constexpr size_type size() const noexcept {

return std::distance( this->begin(), this->end() );
}

/**
* @brief Return an element at a given index
*
* No range checking is performed.
*
* @param[in] i the index
*/
constexpr decltype(auto) operator[]( size_type i ) const noexcept {

return *( std::next( this->begin(), i ) );
}

/**
* @brief Return an element at a given index with range checking
*
* @param[in] i the index
*/
constexpr decltype(auto) at( size_type i ) const {

if ( i >= this->size() ) {

throw std::out_of_range( "Index out of range in IteratorView: " +
std::to_string( i ) + " >= size (" +
std::to_string( this->size() ) + ")" );
}
return this->operator[]( i );
}

/**
* @brief Verify if the IteratorView is equal to another container
*
* @param[in] other the other container to compare with
*/
template < typename Container >
constexpr bool operator==( const Container& other ) const {

return std::equal( this->begin(), this->end(), other.begin(), other.end() );
}

/**
* @brief Verify if the IteratorView is equal to another container
*
* @param[in] other the other container to compare with
*/
template < typename Container >
constexpr bool operator!=( const Container& other ) const {

return !this->operator==( other );
}
using Parent::front;
using Parent::back;
using Parent::empty;
using Parent::size;
using Parent::operator[];
using Parent::at;
using Parent::operator==;
using Parent::operator!=;
};

/**
Expand Down
125 changes: 125 additions & 0 deletions src/tools/ranges/ViewBase.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#ifndef NJOY_TOOLS_RANGES_VIEWBASE
#define NJOY_TOOLS_RANGES_VIEWBASE

// system includes
#include <stdexcept>

// other includes

namespace njoy {
namespace tools {
namespace ranges {

/**
*
* @brief A base class for views
*
* This CRTP base class assumes the Derived range has a begin() and end()
* method that define the begin and end iterator to the Derived range.
*/
template < typename Derived >
class ViewBase {

constexpr Derived& derived() noexcept {

return static_cast< Derived& >( *this );
}

constexpr const Derived& derived() const noexcept {

return static_cast< const Derived& >( *this );
}

public:

/* methods */

/**
* @brief Return the reference to the front element of the view
*/
constexpr decltype(auto) front() const noexcept {

return *( this->derived().begin() );
}

/**
* @brief Return the reference to the back element of the view
*/
constexpr decltype(auto) back() const noexcept {

return *( std::prev( this->derived().end() ) );
}

/**
* @brief Return whether or not the view is empty
*/
constexpr bool empty() const noexcept {

return this->derived().begin() == this->derived().end();
}

/**
* @brief Return the size of the iterator view
*/
constexpr std::size_t size() const noexcept {

return std::distance( this->derived().begin(), this->derived().end() );
}

/**
* @brief Return an element at a given index
*
* No range checking is performed.
*
* @param[in] i the index
*/
constexpr decltype(auto) operator[]( std::size_t i ) const noexcept {

return *( std::next( this->derived().begin(), i ) );
}

/**
* @brief Return an element at a given index with range checking
*
* @param[in] i the index
*/
constexpr decltype(auto) at( std::size_t i ) const {

if ( i >= this->size() ) {

throw std::out_of_range( "Index out of range: " +
std::to_string( i ) + " >= size (" +
std::to_string( this->size() ) + ")" );
}
return this->operator[]( i );
}

/**
* @brief Verify if the IteratorView is equal to another container
*
* @param[in] other the other container to compare with
*/
template < typename Container >
constexpr bool operator==( const Container& other ) const {

return std::equal( this->derived().begin(), this->derived().end(),
other.begin(), other.end() );
}

/**
* @brief Verify if the IteratorView is equal to another container
*
* @param[in] other the other container to compare with
*/
template < typename Container >
constexpr bool operator!=( const Container& other ) const {

return !this->operator==( other );
}
};

} // ranges namespace
} // tools namespace
} // njoy namespace

#endif

0 comments on commit 1a050d1

Please sign in to comment.