-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from njoy/feature/IteratorView
Feature/iterator view
- Loading branch information
Showing
7 changed files
with
351 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ if( DEFINED PROJECT_NAME ) | |
endif() | ||
|
||
project( tools | ||
VERSION 0.2.0 | ||
VERSION 0.3.0 | ||
LANGUAGES CXX | ||
) | ||
|
||
|
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
#include "tools/overload.hpp" | ||
#include "tools/ranges.hpp" | ||
|
||
#include "tools/Log.hpp" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#include "tools/ranges/IteratorView.hpp" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#ifndef NJOY_TOOLS_RANGES_ITERATORVIEW | ||
#define NJOY_TOOLS_RANGES_ITERATORVIEW | ||
|
||
// system includes | ||
#include <iterator> | ||
#include <stdexcept> | ||
|
||
// other includes | ||
|
||
namespace njoy { | ||
namespace tools { | ||
namespace ranges { | ||
|
||
/** | ||
* | ||
* @brief A simple iterator based view class | ||
* | ||
* Currently only defined for random access iterators. | ||
*/ | ||
template < class 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 { | ||
|
||
public: | ||
|
||
using value_type = typename std::iterator_traits< Iterator >::value_type; | ||
using difference_type = typename std::iterator_traits< Iterator >::difference_type; | ||
using size_type = std::size_t; | ||
using pointer = typename std::iterator_traits< Iterator >::pointer; | ||
using reference = typename std::iterator_traits< Iterator >::reference; | ||
using const_reference = const reference; | ||
using iterator = Iterator; | ||
|
||
private: | ||
|
||
/* fields */ | ||
Iterator begin_; | ||
Iterator end_; | ||
|
||
public: | ||
|
||
/* constructor */ | ||
|
||
/** | ||
* @brief Default constructor | ||
*/ | ||
constexpr IteratorView() : IteratorView( Iterator{}, Iterator{} ) {} | ||
|
||
/** | ||
* @brief IteratorView constructor | ||
* | ||
* @param[in] begin the iterator to the beginning of the view | ||
* @param[in] end the iterator to the end of the view | ||
*/ | ||
constexpr IteratorView( Iterator begin, Iterator end ) : | ||
begin_( std::move( begin ) ), end_( std::move( end ) ) {} | ||
|
||
/* methods */ | ||
|
||
/** | ||
* @brief Return the begin iterator to the view | ||
*/ | ||
constexpr iterator begin() const noexcept { return begin_; } | ||
|
||
/** | ||
* @brief Return the end iterator to the view | ||
*/ | ||
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 ); | ||
} | ||
}; | ||
|
||
/** | ||
* @brief Make an IteratorView based on two iterators | ||
* | ||
* @param[in] begin the iterator to the beginning of the view | ||
* @param[in] end the iterator to the end of the view | ||
*/ | ||
template < typename Iterator > | ||
constexpr auto make_view( Iterator&& begin, Iterator&& end ) { | ||
|
||
return IteratorView< Iterator >{ std::forward< Iterator >( begin ), | ||
std::forward< Iterator >( end ) }; | ||
} | ||
|
||
/** | ||
* @brief Make an IteratorView based on a container | ||
* | ||
* @param[in] container the container | ||
*/ | ||
template < typename Container > | ||
constexpr auto make_view( Container& container ) { | ||
|
||
return IteratorView< typename Container::iterator >{ container.begin(), | ||
container.end() }; | ||
} | ||
|
||
/** | ||
* @brief Make an IteratorView based on a container | ||
* | ||
* @param[in] container the container | ||
*/ | ||
template < typename Container > | ||
constexpr auto make_view( const Container& container ) { | ||
|
||
return IteratorView< typename Container::const_iterator >{ container.cbegin(), | ||
container.cend() }; | ||
} | ||
|
||
/** | ||
* @brief Verify if the IteratorView is equal to another container | ||
* | ||
* @param[in] other the other container to compare with | ||
*/ | ||
template < typename Container, typename Iterator > | ||
constexpr bool operator==( const Container& left, | ||
IteratorView< Iterator > right ) { | ||
|
||
return right == left; | ||
} | ||
|
||
/** | ||
* @brief Verify if the IteratorView is equal to another container | ||
* | ||
* @param[in] other the other container to compare with | ||
*/ | ||
template < typename Container, typename Iterator > | ||
constexpr bool operator!=( const Container& left, | ||
IteratorView< Iterator > right ) { | ||
|
||
return right != left; | ||
} | ||
|
||
} // ranges namespace | ||
} // tools namespace | ||
} // njoy namespace | ||
|
||
#endif |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
add_cpp_test( ranges.IteratorView IteratorView.test.cpp ) |
126 changes: 126 additions & 0 deletions
126
src/tools/ranges/IteratorView/test/IteratorView.test.cpp
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// include Catch2 | ||
#include <catch2/catch_test_macros.hpp> | ||
|
||
// what we are testing | ||
#include "tools/ranges/IteratorView.hpp" | ||
|
||
// other includes | ||
|
||
// convenience typedefs | ||
using namespace njoy::tools::ranges; | ||
|
||
SCENARIO( "IteratorView" ) { | ||
|
||
GIVEN( "a container with values" ) { | ||
|
||
std::vector< int > values = { -2, -1, 0, 1, 2 }; | ||
|
||
WHEN( "when iterators are used" ) { | ||
|
||
IteratorView< std::vector< int >::iterator > chunk( values.begin(), values.end() ); | ||
|
||
THEN( "an IteratorView can be constructed and members can be tested" ) { | ||
|
||
CHECK( 5 == chunk.size() ); | ||
CHECK( false == chunk.empty() ); | ||
|
||
CHECK( -2 == chunk[0] ); | ||
CHECK( -1 == chunk[1] ); | ||
CHECK( 0 == chunk[2] ); | ||
CHECK( 1 == chunk[3] ); | ||
CHECK( 2 == chunk[4] ); | ||
|
||
CHECK( -2 == chunk.at( 0 ) ); | ||
CHECK( -1 == chunk.at( 1 ) ); | ||
CHECK( 0 == chunk.at( 2 ) ); | ||
CHECK( 1 == chunk.at( 3 ) ); | ||
CHECK( 2 == chunk.at( 4 ) ); | ||
|
||
CHECK( -2 == chunk.front() ); | ||
CHECK( 2 == chunk.back() ); | ||
} // THEN | ||
|
||
THEN( "an exception is thrown when using an index that is too large or " | ||
"too small" ) { | ||
|
||
CHECK_NOTHROW( chunk.at( 0 ) ); | ||
CHECK_NOTHROW( chunk.at( 4 ) ); | ||
CHECK_THROWS( chunk.at( 5 ) ); | ||
CHECK_THROWS( chunk.at( 10 ) ); | ||
} // THEN | ||
} // WHEN | ||
|
||
WHEN( "when make functions are used" ) { | ||
|
||
auto chunk = make_view( values ); | ||
|
||
THEN( "an IteratorView can be constructed and members can be tested" ) { | ||
|
||
CHECK( 5 == chunk.size() ); | ||
CHECK( false == chunk.empty() ); | ||
|
||
CHECK( -2 == chunk[0] ); | ||
CHECK( -1 == chunk[1] ); | ||
CHECK( 0 == chunk[2] ); | ||
CHECK( 1 == chunk[3] ); | ||
CHECK( 2 == chunk[4] ); | ||
|
||
CHECK( -2 == chunk.at( 0 ) ); | ||
CHECK( -1 == chunk.at( 1 ) ); | ||
CHECK( 0 == chunk.at( 2 ) ); | ||
CHECK( 1 == chunk.at( 3 ) ); | ||
CHECK( 2 == chunk.at( 4 ) ); | ||
|
||
CHECK( -2 == chunk.front() ); | ||
CHECK( 2 == chunk.back() ); | ||
} // THEN | ||
|
||
THEN( "an exception is thrown when using an index that is too large or " | ||
"too small" ) { | ||
|
||
CHECK_NOTHROW( chunk.at( 0 ) ); | ||
CHECK_NOTHROW( chunk.at( 4 ) ); | ||
CHECK_THROWS( chunk.at( 5 ) ); | ||
CHECK_THROWS( chunk.at( 10 ) ); | ||
} // THEN | ||
} // WHEN | ||
} // GIVEN | ||
|
||
GIVEN( "containers and views with values" ) { | ||
|
||
std::vector< double > container1 = { 1., 2., 3., 4. }; | ||
std::vector< double > container2 = { 1., 2., 3. }; | ||
|
||
std::vector< double > copy1 = container1; | ||
std::vector< double > copy2 = container2; | ||
|
||
auto view1 = make_view( copy1 ); | ||
auto view2 = make_view( copy2 ); | ||
|
||
WHEN( "when make comparison functions are used" ) { | ||
|
||
THEN( "views and containers can be compared" ) { | ||
|
||
CHECK( view1 == container1 ); | ||
CHECK( view1 == copy1 ); | ||
CHECK( container1 == view1 ); | ||
CHECK( copy1 == view1 ); | ||
|
||
CHECK( view1 != container2 ); | ||
CHECK( view1 != copy2 ); | ||
CHECK( container2 != view1 ); | ||
CHECK( copy2 != view1 ); | ||
|
||
CHECK( view2 == container2 ); | ||
CHECK( view2 == copy2 ); | ||
CHECK( container2 == view2 ); | ||
CHECK( copy2 == view2 ); | ||
|
||
CHECK( view2 != container1 ); | ||
CHECK( view2 != copy1 ); | ||
CHECK( container1 != view2 ); | ||
CHECK( copy1 != view2 ); | ||
} // THEN | ||
} // WHEN | ||
} // GIVEN | ||
} // SCENARIO |