adapter: add container transform adapter

This commit is contained in:
Danny Robson 2022-06-23 10:58:17 +10:00
parent 9451083f83
commit 2ee2806979
3 changed files with 110 additions and 46 deletions

View File

@ -9,47 +9,15 @@
#include "adapter.hpp"
//#include <vector>
//#include <tuple>
//#include <iostream>
//
//
//using cruft::adapter::scalar;
//
//
//void
//foo (void) {
// std::vector<std::tuple<int,int,int>> vals;
//
// using iterator_t = cruft::adapter::scalar<0, decltype(vals.begin ())>;
//
// static_assert (
// std::is_same<
// typename std::iterator_traits<
// decltype(vals.begin ())
// >::value_type,
// std::tuple<int,int,int>
// >::value
// );
//
// static_assert (
// std::is_same<
// typename std::tuple_element<0, std::tuple<int,int,int>>::type,
// int
// >::value
// );
//
// iterator_t end (vals.end ());
//
// //static_assert (
// // std::is_same<
// // typename iterator_t::reference,
// // //decltype(*std::declval <scalar<0,std::tuple<int,int,int>>> ()),
// // //typename scalar<0,decltype(vals.begin ())>::value_type,
// // int&
// // >::value
// //);
//
// for (auto p = iterator_t (vals.begin ()), last = iterator_t (vals.end ()); p != last; ++p)
// int b = *p;
//}
#include "concepts/named.hpp"
#include <array>
static std::array<int,5> v;
static cruft::adapter::container::transform t (v, [](auto const&) { return false; });
static_assert (
std::is_same_v<
typename std::iterator_traits<decltype(t)::iterator>::value_type,
bool
>
);

View File

@ -3,14 +3,15 @@
* 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>
* Copyright 2015-2022 Danny Robson <danny@nerdcruft.net>
*/
#include "concepts/named.hpp"
#include <cstddef>
#include <iterator>
#include <tuple>
namespace cruft::adapter {
namespace container {
/// An identity proxy for a referenced container.
@ -93,6 +94,95 @@ namespace cruft::adapter {
private:
T &m_target;
};
template <
typename ContainerT,
typename FunctionT
>
requires (
std::is_invocable_v<
FunctionT,
typename std::iterator_traits<typename ContainerT::iterator>::value_type
>
)
class transform {
public:
using value_type = std::invoke_result_t<
FunctionT,
typename std::iterator_traits<typename ContainerT::iterator>::value_type
>;
using pointer = void;
using reference = void;
using difference_type = typename std::iterator_traits<
typename ContainerT::iterator
>::difference_type;
template <typename _ContainerT, typename _FunctionT>
transform (_ContainerT &&_container, _FunctionT &&_function)
: m_container (std::forward<_ContainerT> (_container))
, m_function (std::forward< _FunctionT> (_function ))
{ ; }
auto begin (void) const { return iterator (m_container.begin (), m_function); }
auto end (void) const { return iterator (m_container.end (), m_function); }
class iterator {
private:
using underlying = typename ContainerT::iterator;
public:
// HACK: We really should be using the underlying iterator's
// category. However it's a massive PITA to write this code
// right now.
using iterator_category = std::forward_iterator_tag; //typename std::iterator_traits<underlying>::iterator_category;
using difference_type = typename std::iterator_traits<underlying>::difference_type;
using value_type = transform::value_type;
using pointer = void;
using reference = void;
iterator (
typename ContainerT::iterator _cursor,
FunctionT const &_function
)
: m_cursor (_cursor)
, m_function (_function)
{ ; }
decltype(auto) operator* ()
{
return m_function (*m_cursor);
}
iterator& operator++ ()&
{
++m_cursor;
return *this;
}
bool operator== (iterator const &rhs) const noexcept
{
return m_cursor == rhs.m_cursor;
}
private:
typename ContainerT::iterator m_cursor;
FunctionT const &m_function;
};
private:
ContainerT m_container;
FunctionT m_function;
};
template <typename ContainerT, typename FunctionT>
transform (ContainerT, FunctionT) -> transform<
std::remove_cvref_t<ContainerT>,
std::remove_cvref_t< FunctionT>
>;
}

View File

@ -8,6 +8,12 @@
#pragma once
#include "../view.hpp"
#include <algorithm>
#include <utility>
namespace cruft::iterator {
///////////////////////////////////////////////////////////////////////////
template <typename OutputIt, typename FunctionT>