147 lines
4.7 KiB
C++
147 lines
4.7 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <iterator>
|
|
|
|
|
|
namespace cruft::adapter {
|
|
namespace container {
|
|
/// An identity proxy for a referenced container.
|
|
///
|
|
/// Provided for symmetry with `reverse` and others, so as to allow a
|
|
/// common template interface.
|
|
template <typename ContainerT>
|
|
class identity {
|
|
public:
|
|
identity (ContainerT &_target)
|
|
: m_target (_target)
|
|
{ ; }
|
|
|
|
decltype(auto) begin (void) & { return m_target.begin (); }
|
|
decltype(auto) end (void) & { return m_target.end (); }
|
|
|
|
decltype(auto) begin (void) const& { return m_target.begin (); }
|
|
decltype(auto) end (void) const& { return m_target.end (); }
|
|
|
|
decltype(auto) cbegin (void) const& { return m_target.cbegin (); }
|
|
decltype(auto) cend (void) const& { return m_target.cend (); }
|
|
|
|
private:
|
|
ContainerT &m_target;
|
|
};
|
|
|
|
|
|
/// Creates a reversed proxy for a referenced container.
|
|
///
|
|
/// The target container must remain an l-value.
|
|
///
|
|
/// It is the caller's job to ensure the targeted container remains
|
|
/// valid for the duration of the proxy's lifetime.
|
|
template <typename T>
|
|
class reverse {
|
|
public:
|
|
explicit reverse (T &_target):
|
|
m_target (_target)
|
|
{ ; }
|
|
|
|
auto begin (void) & { return m_target.rbegin (); }
|
|
auto end (void) & { return m_target.rend (); }
|
|
|
|
auto begin (void) const& { return m_target.rbegin (); }
|
|
auto end (void) const& { return m_target.rend (); }
|
|
|
|
auto cbegin (void) const& { return m_target.crbegin (); }
|
|
auto cend (void) const& { return m_target.crend (); }
|
|
|
|
private:
|
|
T &m_target;
|
|
};
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
template <typename Container>
|
|
reverse (Container&) -> reverse<Container>;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
/// Adapter's a container to return indices of the container's data
|
|
/// rather than the values themselves.
|
|
///
|
|
/// The targeted container must be an l-value.
|
|
///
|
|
/// It is the caller's job to ensure the targeted container remains
|
|
/// valid for the duration of the proxy's lifetime.
|
|
template <typename T>
|
|
class indices {
|
|
public:
|
|
using typename T::size_type;
|
|
|
|
explicit indices (T &_target):
|
|
m_target (_target)
|
|
{ ; }
|
|
|
|
size_type begin (void)& { return 0; }
|
|
size_type end (void)& { return m_target.size (); }
|
|
|
|
private:
|
|
T &m_target;
|
|
};
|
|
}
|
|
|
|
|
|
namespace iterator {
|
|
///////////////////////////////////////////////////////////////////////
|
|
/// Adapt's an iterator to return the n-th element of the tuple that
|
|
/// corresponds to the underlying iterator::value_type when
|
|
/// dereferenced.
|
|
template <size_t I, typename IteratorT>
|
|
struct scalar : public std::iterator<
|
|
typename std::iterator_traits<IteratorT>::iterator_category,
|
|
typename std::tuple_element<
|
|
I,
|
|
typename std::iterator_traits<
|
|
IteratorT
|
|
>::value_type
|
|
>::type,
|
|
typename std::iterator_traits<IteratorT>::difference_type
|
|
> {
|
|
public:
|
|
using inner_type = typename std::iterator_traits<IteratorT>::value_type;
|
|
|
|
using value_type = decltype (std::get<I> (std::declval<inner_type> ()));
|
|
using reference = value_type&;
|
|
using const_reference = value_type const&;
|
|
|
|
|
|
explicit scalar (IteratorT _inner):
|
|
m_inner (_inner)
|
|
{ ; }
|
|
|
|
|
|
const_reference operator* (void) const&
|
|
{ return std::get<I> (*m_inner); }
|
|
|
|
reference operator* (void)&
|
|
{ return std::get<I> (*m_inner); }
|
|
|
|
bool operator== (scalar<I,IteratorT> rhs) { return m_inner == rhs.m_inner; }
|
|
bool operator!= (scalar<I,IteratorT> rhs) { return m_inner != rhs.m_inner; }
|
|
|
|
|
|
scalar<I,IteratorT>& operator++ (void)
|
|
{ ++m_inner; return *this; }
|
|
|
|
|
|
private:
|
|
IteratorT m_inner;
|
|
};
|
|
}
|
|
}
|