Merge pull request #147 from samuel3/master

std::hash support for gsl::not_null.
diff --git a/include/array_view.h b/include/array_view.h
index cc7ab23..a2ea49f 100644
--- a/include/array_view.h
+++ b/include/array_view.h
@@ -72,26 +72,7 @@
 	template <typename SizeType>
 	struct SizeTypeTraits
 	{
-		static const SizeType max_value = std::is_signed<SizeType>::value ? static_cast<typename std::make_unsigned<SizeType>::type>(-1) / 2 : static_cast<SizeType>(-1);
-	};
-
-	template <typename T>
-	class arrow_proxy
-	{
-	public:
-		explicit arrow_proxy(T t)
-			: val(t)
-		{}
-		const T operator*() const noexcept
-		{
-			return val;
-		}
-		const T* operator->() const noexcept
-		{
-			return &val;
-		}
-	private:
-		T val;
+		static const SizeType max_value = std::numeric_limits<SizeType>::max();
 	};
 }
 
@@ -118,12 +99,9 @@
 		std::copy(values, values + Rank, elems);
 	}
 
-	// Preconditions: il.size() == rank
-	constexpr index(std::initializer_list<value_type> il) noexcept
-	{
-		fail_fast_assert(il.size() == Rank, "The size of the initializer list must match the rank of the array");
-		std::copy(begin(il), end(il), elems);
-	}
+	template<typename... Ts, bool Enabled = (sizeof...(Ts) == Rank), typename Dummy = std::enable_if_t<Enabled, bool>>
+	constexpr index(Ts... ds) noexcept : elems{ static_cast<value_type>(ds)... }
+	{}
 
 	constexpr index(const index& other) noexcept = default;
 
@@ -730,8 +708,9 @@
 
 	using size_type = SizeType;
 	using index_type = index<rank, size_type>;
-	using iterator = bounds_iterator<index_type>;
-	using const_iterator = bounds_iterator<index_type>;
+	using const_index_type = std::add_const_t<index_type>;
+	using iterator = bounds_iterator<const_index_type>;
+	using const_iterator = bounds_iterator<const_index_type>;
 	using difference_type = ptrdiff_t;
 	using sliced_type = static_bounds<SizeType, RestRanges...>;
 	using mapping_type = contiguous_mapping_tag;
@@ -822,7 +801,7 @@
 	
 	constexpr const_iterator begin() const noexcept
 	{
-		return const_iterator(*this);
+		return const_iterator(*this, index_type{});
 	}
 	
 	constexpr const_iterator end() const noexcept
@@ -845,8 +824,9 @@
 	using difference_type = SizeType;
 	using value_type      = SizeType;
 	using index_type      = index<rank, size_type>;
-	using iterator        = bounds_iterator<index_type>;
-	using const_iterator  = bounds_iterator<index_type>;
+	using const_index_type = std::add_const_t<index_type>;
+	using iterator = bounds_iterator<const_index_type>;
+	using const_iterator = bounds_iterator<const_index_type>;
 	static const int dynamic_rank = rank;
 	static const size_t static_size = dynamic_range;
 	using sliced_type = std::conditional_t<rank != 0, strided_bounds<rank - 1>, void>;
@@ -920,11 +900,11 @@
 	{
 		return m_extents;
 	}
-	const_iterator begin() const noexcept
+	constexpr const_iterator begin() const noexcept
 	{
-		return const_iterator{ *this };
+		return const_iterator{ *this, index_type{} };
 	}
-	const_iterator end() const noexcept
+	constexpr const_iterator end() const noexcept
 	{
 		return const_iterator{ *this, index_bounds() };
 	}
@@ -941,15 +921,11 @@
 struct is_bounds<strided_bounds<Rank, SizeType>> : std::integral_constant<bool, true> {};
 
 template <typename IndexType>
-class bounds_iterator
-	: public std::iterator<std::random_access_iterator_tag,
-		IndexType,
-		ptrdiff_t,
-		const details::arrow_proxy<IndexType>,
-		const IndexType>
+class bounds_iterator: public std::iterator<std::random_access_iterator_tag, IndexType>
 {
 private:
-	using Base = std::iterator <std::random_access_iterator_tag, IndexType, ptrdiff_t, const details::arrow_proxy<IndexType>, const IndexType>;
+	using Base = std::iterator <std::random_access_iterator_tag, IndexType>;
+
 public:
 	static const size_t rank = IndexType::rank;
 	using typename Base::reference;
@@ -959,79 +935,88 @@
 	using index_type = value_type;
 	using index_size_type = typename IndexType::value_type;
 	template <typename Bounds>
-	explicit bounds_iterator(const Bounds& bnd, value_type curr = value_type{}) noexcept
-		: boundary(bnd.index_bounds())
-		, curr(std::move(curr))
+	explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept
+		: boundary(bnd.index_bounds()), curr(std::move(curr))
 	{
 		static_assert(is_bounds<Bounds>::value, "Bounds type must be provided");
 	}
-	reference operator*() const noexcept
+
+	constexpr reference operator*() const noexcept
 	{
 		return curr;
 	}
-	pointer operator->() const noexcept
+
+	constexpr pointer operator->() const noexcept
 	{
-		return details::arrow_proxy<value_type>{ curr };
+		return &curr;
 	}
-	bounds_iterator& operator++() noexcept
+
+	constexpr bounds_iterator& operator++() noexcept
 	{
 		for (size_t i = rank; i-- > 0;)
 		{
-			if (++curr[i] < boundary[i])
+			if (curr[i] < boundary[i] - 1)
 			{
+				curr[i]++;
 				return *this;
 			}
-			else
-			{
-				curr[i] = 0;
-			}
+			curr[i] = 0;
 		}
 		// If we're here we've wrapped over - set to past-the-end.
-		for (size_t i = 0; i < rank; ++i)
-		{
-			curr[i] = boundary[i];
-		}
+		curr = boundary;
 		return *this;
 	}
-	bounds_iterator operator++(int) noexcept
+
+	constexpr bounds_iterator operator++(int) noexcept
 	{
 		auto ret = *this;
 		++(*this);
 		return ret;
 	}
-	bounds_iterator& operator--() noexcept
+
+	constexpr bounds_iterator& operator--() noexcept
 	{
-		for (size_t i = rank; i-- > 0;)
+		if (!less(curr, boundary))
 		{
-			if (curr[i]-- > 0)
-			{
-				return *this;
-			}
-			else
+			// if at the past-the-end, set to last element
+			for (size_t i = 0; i < rank; ++i)
 			{
 				curr[i] = boundary[i] - 1;
 			}
+			return *this;
+		}
+		for (size_t i = rank; i-- > 0;)
+		{
+			if (curr[i] >= 1)
+			{
+				curr[i]--;
+				return *this;
+			}
+			curr[i] = boundary[i] - 1;
 		}
 		// If we're here the preconditions were violated
 		// "pre: there exists s such that r == ++s"
 		fail_fast_assert(false);
 		return *this;
 	}
-	bounds_iterator operator--(int) noexcept
+
+	constexpr bounds_iterator operator--(int) noexcept
 	{
 		auto ret = *this;
 		--(*this);
 		return ret;
 	}
-	bounds_iterator operator+(difference_type n) const noexcept
+
+	constexpr bounds_iterator operator+(difference_type n) const noexcept
 	{
 		bounds_iterator ret{ *this };
 		return ret += n;
 	}
-	bounds_iterator& operator+=(difference_type n) noexcept
+
+	constexpr bounds_iterator& operator+=(difference_type n) noexcept
 	{
 		auto linear_idx = linearize(curr) + n;
-		value_type stride;
+		std::remove_const_t<value_type> stride;
 		stride[rank - 1] = 1;
 		for (size_t i = rank - 1; i-- > 0;)
 		{
@@ -1042,76 +1027,84 @@
 			curr[i] = linear_idx / stride[i];
 			linear_idx = linear_idx % stride[i];
 		}
+		fail_fast_assert(!less(curr, index_type{}) && !less(boundary, curr), "index is out of bounds of the array");
 		return *this;
 	}
-	bounds_iterator operator-(difference_type n) const noexcept
+
+	constexpr bounds_iterator operator-(difference_type n) const noexcept
 	{
 		bounds_iterator ret{ *this };
 		return ret -= n;
 	}
-	bounds_iterator& operator-=(difference_type n) noexcept
+
+	constexpr bounds_iterator& operator-=(difference_type n) noexcept
 	{
 		return *this += -n;
 	}
-	difference_type operator-(const bounds_iterator& rhs) const noexcept
+
+	constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
 	{
 		return linearize(curr) - linearize(rhs.curr);
 	}
-	reference operator[](difference_type n) const noexcept
+
+	constexpr reference operator[](difference_type n) const noexcept
 	{
 		return *(*this + n);
 	}
-	bool operator==(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator==(const bounds_iterator& rhs) const noexcept
 	{
 		return curr == rhs.curr;
 	}
-	bool operator!=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator!=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(*this == rhs);
 	}
-	bool operator<(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator<(const bounds_iterator& rhs) const noexcept
 	{
-		for (size_t i = 0; i < rank; ++i)
-		{
-			if (curr[i] < rhs.curr[i])
-				return true;
-		}
-		return false;
+		return less(curr, rhs.curr);
 	}
-	bool operator<=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator<=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(rhs < *this);
 	}
-	bool operator>(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator>(const bounds_iterator& rhs) const noexcept
 	{
 		return rhs < *this;
 	}
-	bool operator>=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator>=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(rhs > *this);
 	}
+
 	void swap(bounds_iterator& rhs) noexcept
 	{
 		std::swap(boundary, rhs.boundary);
 		std::swap(curr, rhs.curr);
 	}
 private:
-	index_size_type linearize(const value_type& idx) const noexcept
+	constexpr bool less(index_type& one, index_type& other) const noexcept
+	{
+		for (size_t i = 0; i < rank; ++i)
+		{
+			if (one[i] < other[i])
+				return true;
+		}
+		return false;
+	}
+
+	constexpr index_size_type linearize(const value_type& idx) const noexcept
 	{
 		// TODO: Smarter impl.
 		// Check if past-the-end
-		bool pte = true;
-		for (size_t i = 0; i < rank; ++i)
-		{
-			if (idx[i] != boundary[i])
-			{
-				pte = false;
-				break;
-			}
-		}
 		index_size_type multiplier = 1;
 		index_size_type res = 0;
-		if (pte)
+		if (!less(idx, boundary))
 		{
 			res = 1;
 			for (size_t i = rank; i-- > 0;)
@@ -1130,19 +1123,15 @@
 		}
 		return res;
 	}
+
 	value_type boundary;
-	value_type curr;
+	std::remove_const_t<value_type> curr;
 };
 
 template <typename SizeType>
-class bounds_iterator<index<1, SizeType>>
-	: public std::iterator<std::random_access_iterator_tag,
-	index<1, SizeType>,
-	ptrdiff_t,
-	const details::arrow_proxy<index<1, SizeType>>,
-	const index<1, SizeType>>
+class bounds_iterator<index<1, SizeType>> : public std::iterator<std::random_access_iterator_tag, index<1, SizeType>>
 {
-	using Base = std::iterator<std::random_access_iterator_tag, index<1, SizeType>, ptrdiff_t, const details::arrow_proxy<index<1, SizeType>>, const index<1, SizeType>>;
+	using Base = std::iterator<std::random_access_iterator_tag, index<1, SizeType>>;
 
 public:
 	using typename Base::reference;
@@ -1153,96 +1142,116 @@
 	using index_size_type = typename index_type::value_type;
 
 	template <typename Bounds>
-	explicit bounds_iterator(const Bounds &, value_type curr = value_type{}) noexcept
-		: curr( std::move(curr) )
+	constexpr explicit bounds_iterator(const Bounds&, value_type curr) noexcept
+		: curr(std::move(curr))
 	{}
-	reference operator*() const noexcept
+
+	constexpr reference operator*() const noexcept
 	{
 		return curr;
 	}
-	pointer operator->() const noexcept
+
+	constexpr pointer operator->() const noexcept
 	{
-		return details::arrow_proxy<value_type>{ curr };
+		&curr;
 	}
-	bounds_iterator& operator++() noexcept
+
+	constexpr bounds_iterator& operator++() noexcept
 	{
 		++curr;
 		return *this;
 	}
-	bounds_iterator operator++(int) noexcept
+
+	constexpr bounds_iterator operator++(int) noexcept
 	{
 		auto ret = *this;
 		++(*this);
 		return ret;
 	}
-	bounds_iterator& operator--() noexcept
+
+	constexpr bounds_iterator& operator--() noexcept
 	{
 		curr--;
 		return *this;
 	}
-	bounds_iterator operator--(int) noexcept
+
+	constexpr bounds_iterator operator--(int) noexcept
 	{
 		auto ret = *this;
 		--(*this);
 		return ret;
 	}
-	bounds_iterator operator+(difference_type n) const noexcept
+
+	constexpr bounds_iterator operator+(difference_type n) const noexcept
 	{
 		bounds_iterator ret{ *this };
 		return ret += n;
 	}
-	bounds_iterator& operator+=(difference_type n) noexcept
+
+	constexpr bounds_iterator& operator+=(difference_type n) noexcept
 	{
 		curr += n;
 		return *this;
 	}
-	bounds_iterator operator-(difference_type n) const noexcept
+
+	constexpr bounds_iterator operator-(difference_type n) const noexcept
 	{
 		bounds_iterator ret{ *this };
 		return ret -= n;
 	}
-	bounds_iterator& operator-=(difference_type n) noexcept
+
+	constexpr bounds_iterator& operator-=(difference_type n) noexcept
 	{
 		return *this += -n;
 	}
-	difference_type operator-(const bounds_iterator& rhs) const noexcept
+
+	constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
 	{
 		return curr[0] - rhs.curr[0];
 	}
-	reference operator[](difference_type n) const noexcept
+
+	constexpr reference operator[](difference_type n) const noexcept
 	{
 		return curr + n;
 	}
-	bool operator==(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator==(const bounds_iterator& rhs) const noexcept
 	{
 		return curr == rhs.curr;
 	}
-	bool operator!=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator!=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(*this == rhs);
 	}
-	bool operator<(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator<(const bounds_iterator& rhs) const noexcept
 	{
 		return curr[0] < rhs.curr[0];
 	}
-	bool operator<=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator<=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(rhs < *this);
 	}
-	bool operator>(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator>(const bounds_iterator& rhs) const noexcept
 	{
 		return rhs < *this;
 	}
-	bool operator>=(const bounds_iterator& rhs) const noexcept
+
+	constexpr bool operator>=(const bounds_iterator& rhs) const noexcept
 	{
 		return !(rhs > *this);
 	}
-	void swap(bounds_iterator& rhs) noexcept
+
+	constexpr void swap(bounds_iterator& rhs) noexcept
 	{
 		std::swap(curr, rhs.curr);
 	}
+
 private:
-	value_type curr;
+	std::remove_const_t<value_type> curr;
 };
 
 template <typename IndexType>
@@ -1304,10 +1313,11 @@
 	using size_type = typename bounds_type::size_type;
 	using index_type = typename bounds_type::index_type;
 	using value_type = ValueType;
+	using const_value_type = std::add_const_t<value_type>;
 	using pointer = ValueType*;
 	using reference = ValueType&;
 	using iterator = std::conditional_t<std::is_same<typename BoundsType::mapping_type, contiguous_mapping_tag>::value, contiguous_array_view_iterator<basic_array_view>, general_array_view_iterator<basic_array_view>>;
-	using const_iterator = std::conditional_t<std::is_same<typename BoundsType::mapping_type, contiguous_mapping_tag>::value, contiguous_array_view_iterator<basic_array_view<const ValueType, BoundsType>>, general_array_view_iterator<basic_array_view<const ValueType, BoundsType>>>;
+	using const_iterator = std::conditional_t<std::is_same<typename BoundsType::mapping_type, contiguous_mapping_tag>::value, contiguous_array_view_iterator<basic_array_view<const_value_type, BoundsType>>, general_array_view_iterator<basic_array_view<const_value_type, BoundsType>>>;
 	using reverse_iterator = std::reverse_iterator<iterator>;
 	using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 	using sliced_type = std::conditional_t<rank == 1, value_type, basic_array_view<value_type, typename BoundsType::sliced_type>>;
@@ -1360,7 +1370,7 @@
 	}
 	constexpr iterator end() const
 	{
-		return iterator {this};
+		return iterator {this, false};
 	}
 	constexpr const_iterator cbegin() const
 	{
@@ -1368,7 +1378,7 @@
 	}
 	constexpr const_iterator cend() const
 	{
-		return const_iterator {reinterpret_cast<const basic_array_view<const value_type, bounds_type> *>(this)};
+		return const_iterator {reinterpret_cast<const basic_array_view<const value_type, bounds_type> *>(this), false};
 	}
 
 	constexpr reverse_iterator rbegin() const
@@ -1999,8 +2009,8 @@
 	{
 		fail_fast_assert(m_pdata >= m_validator->m_pdata && m_pdata < m_validator->m_pdata + m_validator->size(), "iterator is out of range of the array");
 	}
-	contiguous_array_view_iterator (const ArrayView *container, bool isbegin = false) :
-		m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {	}
+	contiguous_array_view_iterator (const ArrayView *container, bool isbegin) :
+		m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {}
 public:
 	reference operator*() const noexcept
 	{
@@ -2115,16 +2125,16 @@
 	friend class basic_array_view;
 	const ArrayView * m_container;
 	typename ArrayView::bounds_type::iterator m_itr;
-	general_array_view_iterator(const ArrayView *container, bool isbegin = false) :
+	general_array_view_iterator(const ArrayView *container, bool isbegin) :
 		m_container(container), m_itr(isbegin ? m_container->bounds().begin() : m_container->bounds().end())
 	{
 	}
 public:
-	reference operator*() const noexcept
+	reference operator*() noexcept
 	{
 		return (*m_container)[*m_itr];
 	}
-	pointer operator->() const noexcept
+	pointer operator->() noexcept
 	{
 		return &(*m_container)[*m_itr];
 	}
diff --git a/tests/array_view_tests.cpp b/tests/array_view_tests.cpp
index f84e908..3a8acc2 100644
--- a/tests/array_view_tests.cpp
+++ b/tests/array_view_tests.cpp
@@ -16,16 +16,11 @@
 
 #include <UnitTest++/UnitTest++.h> 
 #include <array_view.h>
-#include <numeric>
-#include <limits>
-#include <array>
+
 #include <string>
 #include <vector>
 #include <list>
 #include <iostream>
-#include <functional>
-#include <algorithm>
-
 
 using namespace std;
 using namespace gsl;
@@ -639,23 +634,14 @@
 
 			index<1> index{ 0, 1 };
 			strided_array_view<int, 1> sav8{ arr,{ 1,{ 1,1 } } };
-#ifdef _MSC_VER
 			strided_array_view<int, 1> sav9{ arr,{ { 1,1 },{ 1,1 } } };
-#endif
 			strided_array_view<int, 1> sav10{ av,{ 1,{ 1,1 } } };
-#ifdef _MSC_VER
 			strided_array_view<int, 1> sav11{ av,{ { 1,1 },{ 1,1 } } };
-#endif
+			strided_array_view<int, 2> sav12{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1 } } };
+			strided_array_view<int, 2> sav13{ av.as_array_view(dim<2>(), dim<2>()),{ { 1 },{ 1,1,1 } } };
+			strided_array_view<int, 2> sav14{ av.as_array_view(dim<2>(), dim<2>()),{ { 1,1,1 },{ 1 } } };
 		}
 #endif
-
-		{
-			CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1}} }), fail_fast);
-			CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1}, {1,1,1}} }), fail_fast);
-#ifdef _MSC_VER
-			CHECK_THROW((strided_array_view<int, 2>{ av.as_array_view(dim<2>(), dim<2>()), {{1,1,1}, {1}} }), fail_fast);
-#endif
-		}
 	}
 
 	TEST(strided_array_view_type_conversion)
@@ -839,6 +825,94 @@
 		delete[] arr;
 	}
 
+	TEST(index_constructors)
+	{
+		{
+			// components of the same type
+			index<3> i1(0, 1, 2);
+			CHECK(i1[0] == 0);
+
+			// components of different types
+			size_t c0 = 0;
+			size_t c1 = 1;
+			index<3> i2(c0, c1, 2);
+			CHECK(i2[0] == 0);
+
+			// from array
+			index<3> i3 = { 0,1,2 };
+			CHECK(i3[0] == 0);
+
+			// from other index of the same size type
+			index<3> i4 = i3;
+			CHECK(i4[0] == 0);
+
+			// from other index of bigger size type
+			index<3, short> i5 = i4;
+			CHECK(i5[0] == 0);
+
+			// from other index of smaller size type
+			index<3, long long> i6 = i4;
+			CHECK(i6[0] == 0);
+
+			// default
+			index<3, long long> i7;
+			CHECK(i7[0] == 0);
+
+			// default
+			index<3, long long> i9 = {};
+			CHECK(i9[0] == 0);
+		}
+
+		{
+			// components of the same type
+			index<1> i1(0);
+			CHECK(i1[0] == 0);
+
+			// components of different types
+			size_t c0 = 0;
+			index<1> i2(c0);
+			CHECK(i2[0] == 0);
+
+			// from array
+			index<1> i3 = { 0 };
+			CHECK(i3[0] == 0);
+
+			// from int
+			index<1> i4 = 0;
+			CHECK(i4[0] == 0);
+
+			// from other index of the same size type
+			index<1> i5 = i3;
+			CHECK(i5[0] == 0);
+
+			// from other index of bigger size type
+			index<1, short> i6 = i5;
+			CHECK(i6[0] == 0);
+
+			// from other index of smaller size type
+			index<1, long long> i7 = i6;
+			CHECK(i7[0] == 0);
+
+			// default
+			index<1, long long> i8;
+			CHECK(i8[0] == 0);
+
+			// default
+			index<1, long long> i9 = {};
+			CHECK(i9[0] == 0);
+		}
+
+#ifdef CONFIRM_COMPILATION_ERRORS
+		{
+			index<3> i1(0, 1);
+			index<3> i2(0, 1, 2, 3);
+			index<3> i3 = { 0 };
+			index<3> i4 = { 0, 1, 2, 3 };
+			index<1> i5 = { 0,1 };
+		}
+#endif
+	}
+
 	TEST(index_operations)
 	{
 		size_t a[3] = { 0, 1, 2 };
@@ -925,11 +999,35 @@
 			}
 		}
 
-		size_t idx = 0;
-		for (auto num : section)
+		size_t check_sum = 0;
+		for (size_t i = 0; i < length; ++i)
 		{
-			CHECK(num == av[idx][1]);
-			idx++;
+			check_sum += av[i][1];
+		}
+
+		{
+			size_t idx = 0;
+			size_t sum = 0;
+			for (auto num : section)
+			{
+				CHECK(num == av[idx][1]);
+				sum += num;
+				idx++;
+			}
+
+			CHECK(sum == check_sum);
+		}
+		{
+			size_t idx = length - 1;
+			size_t sum = 0;
+			for (auto iter = section.rbegin(); iter != section.rend(); ++iter)
+			{
+				CHECK(*iter == av[idx][1]);
+				sum += *iter;
+				idx--;
+			}
+
+			CHECK(sum == check_sum);
 		}
 	}
 
@@ -1688,7 +1786,7 @@
 		CHECK_THROW(f(), fail_fast);
 	}
 
-	TEST(AsWriteableBytes)		
+	TEST(AsWriteableBytes)
 	{
 		int a[] = { 1, 2, 3, 4 };
 
@@ -1714,7 +1812,36 @@
 			CHECK(wav.data() == (byte*)&a[0]);
 			CHECK(wav.length() == sizeof(a));
 		}
+	}
 
+	TEST(NonConstIterator)
+	{
+		int a[] = { 1, 2, 3, 4 };
+
+		{
+			array_view<int, dynamic_range> av = a;
+			auto wav = av.as_writeable_bytes();
+			for (auto& b : wav)
+			{
+				b = byte(0);
+			}
+			for (size_t i = 0; i < 4; ++i)
+			{
+				CHECK(a[i] == 0);
+			}
+		}
+
+		{
+			array_view<int, dynamic_range> av = a;
+			for (auto& n : av)
+			{
+				n = 1;
+			}
+			for (size_t i = 0; i < 4; ++i)
+			{
+				CHECK(a[i] == 1);
+			}
+		}
 	}
 
 	TEST(ArrayViewComparison)