Skip to content

Commit

Permalink
Several cleanups to "ring.h".
Browse files Browse the repository at this point in the history
- Add `#pragma once`.
- Add a non-member ADL swap() for rings.
- Fix up the namespace of operator+= and operator-= for ring iterators.
- Fix up (it + n) and (it - n) for ring iterators.
- Add (it - it) for ring iterators.
- Fix a typo in (a >= b) for ring iterators, and make (a <= b) == !(b > a).
- Add the implicit conversion from iterator to const_iterator.
- `#if 0` the broken tests for unimplemented static_ring and dynamic_ring.

Fixes #75, #77, #90, #93, #101.
  • Loading branch information
Quuxplusone committed May 12, 2017
1 parent 9e9be1f commit 5013c6c
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 44 deletions.
86 changes: 63 additions & 23 deletions SG14/ring.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include <cstddef>
#include <type_traits>
#include <iterator>
Expand Down Expand Up @@ -94,6 +96,9 @@ namespace sg14
Popper m_popper;
};

template<typename T, class Popper>
void swap(ring_span<T, Popper>&, ring_span<T, Popper>&) noexcept;

template <typename Ring, bool is_const>
class ring_iterator
{
Expand All @@ -105,6 +110,8 @@ namespace sg14
using reference = typename std::conditional_t<is_const, const value_type, value_type>&;
using iterator_category = std::random_access_iterator_tag;

operator ring_iterator<Ring, true>() const noexcept;

template <bool C>
bool operator==(const ring_iterator<Ring, C>& rhs) const noexcept;
template <bool C>
Expand All @@ -124,18 +131,28 @@ namespace sg14
type& operator--() noexcept;
type operator--(int) noexcept;

friend type& operator+=(type& it, int i) noexcept;
friend type& operator-=(type& it, int i) noexcept;
type& operator+=(std::ptrdiff_t i) noexcept;
type& operator-=(std::ptrdiff_t i) noexcept;

template<bool C>
std::ptrdiff_t operator-(const ring_iterator<Ring, C>& rhs) const noexcept;

// Example implementation
private:
friend Ring;
friend class ring_iterator<Ring, !is_const>;
using size_type = typename Ring::size_type;
ring_iterator(size_type idx, std::conditional_t<is_const, const Ring, Ring>* rv) noexcept;
size_type m_idx;
std::conditional_t<is_const, const Ring, Ring>* m_rv;
};
}

template <typename Ring, bool C>
ring_iterator<Ring, C> operator+(ring_iterator<Ring, C> it, std::ptrdiff_t) noexcept;

template <typename Ring, bool C>
ring_iterator<Ring, C> operator-(ring_iterator<Ring, C> it, std::ptrdiff_t) noexcept;
} // namespace sg14

// Sample implementation

Expand Down Expand Up @@ -339,6 +356,12 @@ void sg14::ring_span<T, Popper>::increase_size() noexcept
}
}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const>::operator sg14::ring_iterator<Ring, true>() const noexcept
{
return sg14::ring_iterator<Ring, true>(m_idx, m_rv);
}

template <typename Ring, bool is_const>
template<bool C>
bool sg14::ring_iterator<Ring, is_const>::operator==(const sg14::ring_iterator<Ring, C>& rhs) const noexcept
Expand All @@ -364,21 +387,21 @@ template <typename Ring, bool is_const>
template<bool C>
bool sg14::ring_iterator<Ring, is_const>::operator<=(const sg14::ring_iterator<Ring, C>& rhs) const noexcept
{
return (m_idx <= rhs.m_idx) && (m_rv == rhs.m_rv);
return !(rhs < *this);
}

template <typename Ring, bool is_const>
template<bool C>
bool sg14::ring_iterator<Ring, is_const>::operator>(const sg14::ring_iterator<Ring, C>& rhs) const noexcept
{
return (m_idx > rhs.m_idx) && (m_rv == rhs.m_rv);
return (rhs < *this);
}

template <typename Ring, bool is_const>
template<bool C>
bool sg14::ring_iterator<Ring, is_const>::operator>=(const sg14::ring_iterator<Ring, C>& rhs) const noexcept
{
return (m_idx > rhs.m_idx) && (m_rv == rhs.m_rv);
return !(*this < rhs);
}

template <typename Ring, bool is_const>
Expand Down Expand Up @@ -418,17 +441,24 @@ sg14::ring_iterator<Ring, is_const> sg14::ring_iterator<Ring, is_const>::operato
}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const>& operator+=(sg14::ring_iterator<Ring, is_const>& it, int i) noexcept
sg14::ring_iterator<Ring, is_const>& sg14::ring_iterator<Ring, is_const>::operator+=(std::ptrdiff_t i) noexcept
{
this->m_idx += i;
return *this;
}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const>& sg14::ring_iterator<Ring, is_const>::operator-=(std::ptrdiff_t i) noexcept
{
it.m_idx += i;
return it;
this->m_idx -= i;
return *this;
}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const>& operator-=(sg14::ring_iterator<Ring, is_const>& it, int i) noexcept
template<bool C>
std::ptrdiff_t sg14::ring_iterator<Ring, is_const>::operator-(const sg14::ring_iterator<Ring, C>& rhs) const noexcept
{
it.m_idx -= i;
return it;
return static_cast<std::ptrdiff_t>(this->m_idx) - static_cast<std::ptrdiff_t>(rhs.m_idx);
}

template <typename Ring, bool is_const>
Expand All @@ -437,16 +467,26 @@ sg14::ring_iterator<Ring, is_const>::ring_iterator(typename sg14::ring_iterator<
, m_rv(rv)
{}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const> operator+(sg14::ring_iterator<Ring, is_const> it, int i) noexcept
{
it += i;
return it;
}

template <typename Ring, bool is_const>
sg14::ring_iterator<Ring, is_const> operator-(sg14::ring_iterator<Ring, is_const> it, int i) noexcept
namespace sg14
{
it -= i;
return it;
}
template<typename T, class Popper>
void swap(ring_span<T, Popper>& a, ring_span<T, Popper>& b) noexcept
{
a.swap(b);
}

template <typename Ring, bool C>
ring_iterator<Ring, C> operator+(ring_iterator<Ring, C> it, std::ptrdiff_t i) noexcept
{
it += i;
return it;
}

template <typename Ring, bool C>
ring_iterator<Ring, C> operator-(ring_iterator<Ring, C> it, std::ptrdiff_t i) noexcept
{
it -= i;
return it;
}
} // namespace sg14
9 changes: 5 additions & 4 deletions SG14_test/SG14_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

#include <cassert>


#if 0
void sg14_test::static_ring_test()
{
assert(!"Please check in definition of sg14::static_ring.");
#if 0
sg14::static_ring<int, 5> Q;

Q.push(7);
Expand Down Expand Up @@ -54,14 +55,14 @@ void sg14_test::static_ring_test()
assert(Q5.size() == 5);
assert(Q5.front() == 6);
assert(Q5.back() == 10);
#endif
}
#endif


#if 0
void sg14_test::dynamic_ring_test()
{
assert(!"Please check in definition of sg14::dynamic_ring.");
#if 0
sg14::dynamic_ring<int> Q(8);

assert(Q.push(7));
Expand Down Expand Up @@ -105,5 +106,5 @@ void sg14_test::dynamic_ring_test()
assert(Q5.size() == 5);
assert(Q5.front() == 6);
assert(Q5.back() == 10);
#endif
}
#endif
10 changes: 3 additions & 7 deletions SG14_test/SG14_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ namespace sg14_test
{
void inplace_function_test();
void transcode_test();
void ring_test();
void static_ring_test();
void dynamic_ring_test();
void thread_communication_test();
void filter_test();
void unstable_remove_test();
void uninitialized();
void ring_tests();
void unstable_remove_test();
void uninitialized();
}

#endif
11 changes: 4 additions & 7 deletions SG14_test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ int main(int, char *[])
{
sg14_test::inplace_function_test();
sg14_test::transcode_test();
sg14_test::ring_test();
sg14_test::thread_communication_test();
sg14_test::filter_test();
sg14_test::ring_tests();
sg14_test::unstable_remove_test();
sg14_test::uninitialized();
sg14_test::uninitialized();

puts("tests completed");
puts("tests completed");

return 0;
return 0;
}

52 changes: 49 additions & 3 deletions SG14_test/ring_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <iostream>
#include <numeric>

void sg14_test::ring_test()
static void ring_test()
{
std::array<int, 5> A;
std::array<int, 5> B;
Expand Down Expand Up @@ -52,7 +52,7 @@ void sg14_test::ring_test()
puts("Ring test completed.\n");
}

void sg14_test::thread_communication_test()
static void thread_communication_test()
{
std::array<int, 10> A;
sg14::ring_span<int> buffer(std::begin(A), std::end(A));
Expand Down Expand Up @@ -91,7 +91,7 @@ void sg14_test::thread_communication_test()
});
}

void sg14_test::filter_test()
static void filter_test()
{
std::array< double, 3 > A;
sg14::ring_span< double > buffer( std::begin( A ), std::end( A ) );
Expand All @@ -111,3 +111,49 @@ void sg14_test::filter_test()
assert( std::inner_product( buffer.begin(), buffer.end(), filter_coefficients.begin(), 0.0 ) == 5.0 );
puts( "Filter example completed.\n" );
}

static void iterator_regression_test()
{
std::array<double, 3> A;
sg14::ring_span<double> r(A.begin(), A.end());
r.push_back(1.0);
decltype(r)::iterator it = r.end();
decltype(r)::const_iterator cit = r.end(); // test conversion from non-const to const
assert(it == cit); // test comparison of const and non-const
assert(it + 0 == it);
assert(it - 1 == r.begin());
assert(cit + 0 == cit);
assert(cit - 1 == r.cbegin());
assert(it - cit == 0);
assert(cit - r.begin() == 1);

std::array<double, 4> B;
sg14::ring_span<double> r2(B.begin(), B.end());
swap(r, r2); // test existence of ADL swap()

// Set up the ring for the TEST_OP tests below.
r = sg14::ring_span<double>(A.begin(), A.end(), A.begin(), 2);
assert(r.size() == 2);

#define TEST_OP(op, a, b, c) \
assert(a(r.begin() op r.end())); \
assert(b(r.end() op r.begin())); \
assert(c(r.begin() op r.begin()))
#define _
TEST_OP(==, !, !, _);
TEST_OP(!=, _, _, !);
TEST_OP(<, _, !, !);
TEST_OP(<=, _, !, _);
TEST_OP(>, !, _, !);
TEST_OP(>=, !, _, _);
#undef _
#undef TEST_OP
}

void sg14_test::ring_tests()
{
ring_test();
thread_communication_test();
filter_test();
iterator_regression_test();
}

0 comments on commit 5013c6c

Please sign in to comment.