Skip to content
Snippets Groups Projects
Commit 5f98218f authored by Jan Trávníček's avatar Jan Trávníček
Browse files

add range class

parent 817d66f3
No related branches found
No related tags found
No related merge requests found
Pipeline #
/*
* range.hpp as proposed http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html by Jeffrey Yasskin <jyasskin@google.com>
*
* Created on: May 28, 2015
* Author: Jan Travnicek
*/
#ifndef __RANGE_HPP_
#define __RANGE_HPP_
#include <utility>
#include <iterator>
namespace std {
template<typename Iterator>
class range {
Iterator m_begin;
Iterator m_end;
public:
// types
typedef typename iterator_traits< Iterator >::iterator_category iterator_category;
typedef typename iterator_traits< Iterator >::value_type value_type;
typedef typename iterator_traits< Iterator >::difference_type difference_type;
typedef typename iterator_traits< Iterator >::reference reference;
typedef typename iterator_traits< Iterator >::pointer pointer;
// constructors
range() {
}
constexpr range(Iterator begin, Iterator end) : m_begin ( begin ), m_end ( end ) {
}
// iterator access
constexpr Iterator begin() const {
return m_begin;
}
constexpr Iterator end() const {
return m_end;
}
// element access
constexpr reference front() const {
return * m_begin;
}
constexpr reference back() const {
return * ( m_end - 1 );
}
constexpr reference operator[](difference_type index) const {
return m_begin [ index ];
}
// size
constexpr bool empty() const {
return m_begin == m_end;
}
constexpr difference_type size() const {
return std::distance ( m_begin, m_end );
}
// traversal from the beginning of the range
void pop_front() {
++ m_begin;
}
void pop_front(difference_type n) {
m_begin = m_begin + n;
}
// traversal from the end of the range
void pop_back() {
-- m_end;
}
void pop_back(difference_type n) {
m_end = m_end - n;
}
// creating derived ranges
pair< range, range > split(difference_type index) const {
return std::make_pair ( slice ( 0, index ), slice ( index, 0 ) );
}
range slice(difference_type start, difference_type stop) const {
return range ( ( start >= 0 ? m_begin : m_end ) + start, ( stop > 0 ? m_begin : m_end ) + stop );
}
range slice(difference_type start) const {
return slice ( start, 0 );
}
};
template < typename Iter >
std::range < Iter > make_range ( Iter begin, Iter end ) {
return std::range < Iter > ( begin, end );
}
template < typename Container >
auto make_range ( Container & container ) {
return std::make_range ( container.begin ( ), container.end ( ) );
}
template < typename Container >
auto make_range ( const Container & container ) {
return std::make_range ( container.begin ( ), container.end ( ) );
}
} /* namespace std */
#endif /* __RANGE_HPP_ */
#ifndef __ALIB_INTERNAL_STD_EXTENSION_
#define __ALIB_INTERNAL_STD_EXTENSION_
#include "extensions/range.hpp"
#undef __ALIB_INTERNAL_STD_EXTENSION_
#else
#endif /* __ALIB_INTERNAL_STD_EXTENSION_ */
#include "RangeTest.h"
#include <range>
#include <vector>
#include <list>
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( RangeTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION ( RangeTest );
void RangeTest::setUp ( ) {
}
void RangeTest::tearDown ( ) {
}
void RangeTest::constructorTest ( ) {
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::range < int * > ra1 ( arr, arr + sizeof ( arr ) / sizeof ( * arr ) );
std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::range < std::vector < int >::iterator > rv1 ( v1.begin ( ), v1.end ( ) );
CPPUNIT_ASSERT ( ( std::equal ( ra1.begin ( ), ra1.end ( ), rv1.begin ( ), rv1.end ( ) ) ) );
auto rv2 = std::make_range ( v1 );
CPPUNIT_ASSERT ( ( std::equal ( rv1.begin ( ), rv1.end ( ), rv2.begin ( ), rv2.end ( ) ) ) );
}
void RangeTest::sizeTest ( ) {
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::range < int * > ra1 ( arr, arr + sizeof ( arr ) / sizeof ( * arr ) );
CPPUNIT_ASSERT ( ra1.size ( ) == 10 );
std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::range < std::vector < int >::iterator > rv1 ( v1.begin ( ), v1.end ( ) );
CPPUNIT_ASSERT ( rv1.size ( ) == 10 );
std::list < int > l1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::range < std::list < int >::iterator > rl1 ( l1.begin ( ), l1.end ( ) );
CPPUNIT_ASSERT ( rl1.size ( ) == 10 );
}
void RangeTest::splitTest ( ) {
std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto r1 = std::make_range ( v1 );
std::vector < int > v2 = { 0, 1, 2 };
auto r2 = std::make_range ( v2 );
std::vector < int > v3 = { 3, 4, 5, 6, 7, 8, 9 };
auto r3 = std::make_range ( v3 );
auto splitted = r1.split ( 3 );
CPPUNIT_ASSERT ( ( std::equal ( splitted.first.begin ( ), splitted.first.end ( ), r2.begin ( ), r2.end ( ) ) ) );
CPPUNIT_ASSERT ( ( std::equal ( splitted.second.begin ( ), splitted.second.end ( ), r3.begin ( ), r3.end ( ) ) ) );
}
void RangeTest::sliceTest ( ) {
std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto r1 = std::make_range ( v1 );
std::vector < int > v2 = { 4, 5, 6 };
auto r2 = std::make_range ( v2 );
auto sliced = r1.slice ( 4, -3 );
CPPUNIT_ASSERT ( ( std::equal ( sliced.begin ( ), sliced.end ( ), r2.begin ( ), r2.end ( ) ) ) );
}
#ifndef RANGE_TEST_H_
#define RANGE_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
class RangeTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE ( RangeTest );
CPPUNIT_TEST ( constructorTest );
CPPUNIT_TEST ( sizeTest );
CPPUNIT_TEST ( splitTest );
CPPUNIT_TEST ( sliceTest );
CPPUNIT_TEST_SUITE_END ( );
public:
void setUp ( );
void tearDown ( );
void constructorTest ( );
void sizeTest ( );
void splitTest ( );
void sliceTest ( );
};
#endif // RANGE_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment