Danny Robson
f6056153e3
This places, at long last, the core library code into the same namespace as the extended library code.
149 lines
4.1 KiB
C++
149 lines
4.1 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-2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#ifndef CRUFT_UTIL_TUPLE_VALUE_HPP
|
|
#define CRUFT_UTIL_TUPLE_VALUE_HPP
|
|
|
|
#include "index.hpp"
|
|
#include "../types.hpp"
|
|
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <tuple>
|
|
#include <utility>
|
|
|
|
|
|
namespace cruft::tuple::value {
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/// Call a provided functor of type FunctionT with each value in a
|
|
/// provided tuple-like object TupleT
|
|
template<
|
|
typename FunctionT,
|
|
typename TupleT,
|
|
std::size_t S = 0
|
|
>
|
|
void
|
|
each (FunctionT &&func, TupleT &&value)
|
|
{
|
|
using tuple_t = std::decay_t<TupleT>;
|
|
static_assert (S < std::tuple_size_v<tuple_t>);
|
|
|
|
std::invoke (func, std::get<S> (value));
|
|
|
|
if constexpr (S + 1 < std::tuple_size_v<tuple_t>) {
|
|
each<FunctionT,TupleT,S+1> (std::forward<FunctionT> (func), std::forward<TupleT> (value));
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
namespace detail {
|
|
template <typename FuncT, typename ArgT, std::size_t ...Indices>
|
|
auto
|
|
map (std::index_sequence<Indices...>, FuncT &&func, ArgT &&arg)
|
|
{
|
|
return std::tuple (std::invoke (func, std::get<Indices> (arg))...);
|
|
}
|
|
};
|
|
|
|
|
|
/// returns a tuple of the result of applying the provided function to
|
|
/// each value of the supplied tuple.
|
|
template <
|
|
typename FuncT,
|
|
typename ArgT,
|
|
typename IndicesV = std::make_index_sequence<
|
|
std::tuple_size_v<std::decay_t<ArgT>>
|
|
>
|
|
>
|
|
auto map (FuncT &&func, ArgT &&arg)
|
|
{
|
|
return detail::map (IndicesV{}, func, arg);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// return a tuple that contains the 'nth' element from each of the supplied
|
|
// tuple-like arguments
|
|
template <size_t N, typename ...TupleT>
|
|
auto
|
|
nth (TupleT&&...args)
|
|
{
|
|
return std::make_tuple (
|
|
std::get<N> (args)...
|
|
);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
namespace detail {
|
|
template <typename ...TupleT, size_t ...Elements>
|
|
auto
|
|
zip (std::index_sequence<Elements...>, TupleT &&...args)
|
|
{
|
|
return std::make_tuple (
|
|
nth<Elements> (args...)...
|
|
);
|
|
}
|
|
};
|
|
|
|
|
|
/// converts m arguments of n-tuples into one m-tuple of n-tuples by taking
|
|
/// successive elements from each argument tuple.
|
|
///
|
|
/// eg, zip (('a', 1.f), (0, nullptr)) becomes (('a', 0), (1.f, nullptr))
|
|
template <typename ...Args >
|
|
auto
|
|
zip (Args &&...args)
|
|
{
|
|
static_assert (sizeof...(args) > 0);
|
|
// ensure all the types have the same static size
|
|
using all_t = std::tuple<std::decay_t<Args>...>;
|
|
using first_t = std::tuple_element_t<0,all_t>;
|
|
|
|
static constexpr auto arity = std::tuple_size_v<first_t>;
|
|
static_assert ((
|
|
(arity == std::tuple_size_v<std::decay_t<Args>>) && ...
|
|
));
|
|
|
|
return detail::zip (
|
|
std::make_index_sequence<arity> {},
|
|
std::forward<Args> (args)...
|
|
);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
namespace detail {
|
|
template <typename TupleT, size_t ...Indices>
|
|
auto
|
|
reverse (index::indices<Indices...>, TupleT &&val)
|
|
{
|
|
return std::make_tuple (
|
|
std::get<Indices> (val)...
|
|
);
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
template <typename TupleT>
|
|
auto
|
|
reverse (TupleT &&val)
|
|
{
|
|
return detail::reverse (
|
|
index::make_reverse_t<
|
|
std::tuple_size_v<std::decay_t<TupleT>>
|
|
> {},
|
|
std::forward<TupleT> (val)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|