tuple/variadic: split into type/value/pack operations
This commit is contained in:
parent
f3f3666877
commit
12d401b98b
@ -368,8 +368,8 @@ list (
|
|||||||
time.hpp
|
time.hpp
|
||||||
time/parse.hpp
|
time/parse.hpp
|
||||||
time/parse8601.cpp
|
time/parse8601.cpp
|
||||||
tuple.cpp
|
tuple/type.hpp
|
||||||
tuple.hpp
|
tuple/value.hpp
|
||||||
typeidx.cpp
|
typeidx.cpp
|
||||||
typeidx.hpp
|
typeidx.hpp
|
||||||
types/bits.hpp
|
types/bits.hpp
|
||||||
|
@ -22,10 +22,9 @@
|
|||||||
|
|
||||||
// we specifically rely on vector<bool> to compute a few logical operations
|
// we specifically rely on vector<bool> to compute a few logical operations
|
||||||
#include "../vector.hpp"
|
#include "../vector.hpp"
|
||||||
|
#include "../tuple/value.hpp"
|
||||||
#include "../debug.hpp"
|
#include "../debug.hpp"
|
||||||
#include "../maths.hpp"
|
#include "../maths.hpp"
|
||||||
#include "../tuple.hpp"
|
|
||||||
#include "../preprocessor.hpp"
|
#include "../preprocessor.hpp"
|
||||||
#include "../types/bits.hpp"
|
#include "../types/bits.hpp"
|
||||||
|
|
||||||
@ -495,7 +494,7 @@ namespace util {
|
|||||||
return RetT {
|
return RetT {
|
||||||
std::apply (
|
std::apply (
|
||||||
func,
|
func,
|
||||||
::util::tuple::convert (
|
::util::tuple::value::map (
|
||||||
static_cast<
|
static_cast<
|
||||||
const value_t& (&)(const part_t&)
|
const value_t& (&)(const part_t&)
|
||||||
> (
|
> (
|
||||||
|
@ -420,7 +420,7 @@ namespace util {
|
|||||||
izip (const ContainerT&... data)
|
izip (const ContainerT&... data)
|
||||||
{
|
{
|
||||||
return zip (
|
return zip (
|
||||||
::util::make_indices (::util::variadic::first (data...)),
|
::util::make_indices (::util::variadic::get<0> (data...)),
|
||||||
data...
|
data...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "../pool.hpp"
|
#include "../pool.hpp"
|
||||||
|
|
||||||
#include "../tuple.hpp"
|
|
||||||
|
|
||||||
#include "ticketlock.hpp"
|
#include "ticketlock.hpp"
|
||||||
#include "semaphore.hpp"
|
#include "semaphore.hpp"
|
||||||
#include "flag.hpp"
|
#include "flag.hpp"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "tuple.hpp"
|
#include "tuple/type.hpp"
|
||||||
|
#include "tuple/value.hpp"
|
||||||
|
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
@ -17,12 +18,19 @@ main ()
|
|||||||
{
|
{
|
||||||
util::TAP::logger tap;
|
util::TAP::logger tap;
|
||||||
|
|
||||||
|
static_assert (
|
||||||
|
util::tuple::type::index<
|
||||||
|
std::tuple<float,int,void>,
|
||||||
|
int
|
||||||
|
>::value == 1
|
||||||
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto tuple = std::make_tuple (1,2,3,4);
|
auto tuple = std::make_tuple (1,2,3,4);
|
||||||
std::vector<int> expected {{ 1, 2, 3, 4 }};
|
std::vector<int> expected {{ 1, 2, 3, 4 }};
|
||||||
|
|
||||||
std::vector<int> actual;
|
std::vector<int> actual;
|
||||||
util::tuple::for_each ([&actual] (auto i) { actual.push_back (i); }, tuple);
|
util::tuple::value::each ([&actual] (auto i) { actual.push_back (i); }, tuple);
|
||||||
|
|
||||||
tap.expect_eq (actual, expected, "value iteration");
|
tap.expect_eq (actual, expected, "value iteration");
|
||||||
}
|
}
|
||||||
@ -38,7 +46,7 @@ main ()
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::type_index> actual;
|
std::vector<std::type_index> actual;
|
||||||
util::tuple::for_type<decltype(tuple)> ([&actual] (auto i) {
|
util::tuple::type::each<decltype(tuple)> ([&actual] (auto i) {
|
||||||
actual.push_back (typeid (typename decltype(i)::type));
|
actual.push_back (typeid (typename decltype(i)::type));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -51,7 +59,7 @@ main ()
|
|||||||
|
|
||||||
{
|
{
|
||||||
using src_t = std::tuple<std::string>;
|
using src_t = std::tuple<std::string>;
|
||||||
using dst_t = typename util::tuple::map<src_t, int_mapper>::type;
|
using dst_t = typename util::tuple::type::map<src_t, int_mapper>::type;
|
||||||
|
|
||||||
tap.expect (std::is_same<dst_t, std::tuple<int>>::value, "tuple type mapping");
|
tap.expect (std::is_same<dst_t, std::tuple<int>>::value, "tuple type mapping");
|
||||||
}
|
}
|
||||||
|
19
tuple.cpp
19
tuple.cpp
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tuple.hpp"
|
|
||||||
|
|
||||||
// Make sure _someone_ includes the header for syntax checking
|
|
229
tuple.hpp
229
tuple.hpp
@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __UTIL_TUPLE_HPP
|
|
||||||
#define __UTIL_TUPLE_HPP
|
|
||||||
|
|
||||||
#include "types.hpp"
|
|
||||||
#include "variadic.hpp"
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
|
|
||||||
namespace util::tuple {
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
/// call a provided object with type_tag<T> for each type in a tuple
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
typename F,
|
|
||||||
size_t S = 0
|
|
||||||
>
|
|
||||||
typename std::enable_if<
|
|
||||||
S == std::tuple_size<T>::value,
|
|
||||||
void
|
|
||||||
>::type
|
|
||||||
for_type (F)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template<
|
|
||||||
typename T,
|
|
||||||
typename F,
|
|
||||||
size_t S = 0
|
|
||||||
>
|
|
||||||
typename std::enable_if<
|
|
||||||
S < std::tuple_size<T>::value,
|
|
||||||
void
|
|
||||||
>::type
|
|
||||||
for_type (F f)
|
|
||||||
{
|
|
||||||
using E = typename std::tuple_element<S,T>::type;
|
|
||||||
|
|
||||||
f (type_tag<E> {});
|
|
||||||
for_type<T,F,S+1> (f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T, typename F>
|
|
||||||
auto for_type (F f, T t)
|
|
||||||
{ return for_type<decltype(t)> (f); }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
/// call a provided object with each value in a tuple
|
|
||||||
template <
|
|
||||||
size_t S = 0,
|
|
||||||
typename F,
|
|
||||||
typename ...T
|
|
||||||
>
|
|
||||||
typename std::enable_if<
|
|
||||||
S == sizeof...(T),
|
|
||||||
void
|
|
||||||
>::type
|
|
||||||
for_each (F, const std::tuple<T...>&)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template<
|
|
||||||
size_t S = 0,
|
|
||||||
typename F,
|
|
||||||
typename ...T
|
|
||||||
>
|
|
||||||
typename std::enable_if<
|
|
||||||
S < sizeof...(T),
|
|
||||||
void
|
|
||||||
>::type
|
|
||||||
for_each (F f, const std::tuple<T...> &t)
|
|
||||||
{
|
|
||||||
f (std::get<S> (t));
|
|
||||||
for_each<S+1,F,T...> (f, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Statically map the member types of a tuple via F<>::type
|
|
||||||
///
|
|
||||||
/// T: tuple type
|
|
||||||
/// F: type mapping object, conversion uses F<>::type
|
|
||||||
/// I: tuple indexing helper
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
template <
|
|
||||||
typename
|
|
||||||
> class F,
|
|
||||||
typename I = std::make_index_sequence<
|
|
||||||
std::tuple_size<T>::value
|
|
||||||
>
|
|
||||||
>
|
|
||||||
struct map;
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <
|
|
||||||
typename T,
|
|
||||||
template <
|
|
||||||
typename
|
|
||||||
> class F,
|
|
||||||
size_t ...I
|
|
||||||
>
|
|
||||||
struct map<
|
|
||||||
T,
|
|
||||||
F,
|
|
||||||
std::index_sequence<I...>
|
|
||||||
> {
|
|
||||||
typedef std::tuple<
|
|
||||||
typename F<
|
|
||||||
typename std::tuple_element<I, T>::type
|
|
||||||
>::type...
|
|
||||||
> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace detail {
|
|
||||||
template <typename FuncT, typename ArgT, std::size_t ...Indices>
|
|
||||||
auto
|
|
||||||
convert (std::index_sequence<Indices...>, FuncT &&func, ArgT &&arg)
|
|
||||||
{
|
|
||||||
return std::tuple (std::invoke (func, std::get<Indices> (arg))...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename FuncT,
|
|
||||||
typename ArgT,
|
|
||||||
typename IndicesV = std::make_index_sequence<
|
|
||||||
std::tuple_size_v<std::decay_t<ArgT>>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
auto convert (FuncT &&func, ArgT &&arg)
|
|
||||||
{
|
|
||||||
return detail::convert (IndicesV{}, func, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
/// do nothing with a set of parameters.
|
|
||||||
///
|
|
||||||
/// useful for temporarily silencing unused argument warnings in parameter
|
|
||||||
/// packs, or for avoiding assignment of [[gnu::warn_unused_result]] to a
|
|
||||||
/// temporary value we'd just cast to void anyway (GCC#66425).
|
|
||||||
///
|
|
||||||
/// it is guaranteed that this function will never be defined out in
|
|
||||||
/// debug/release/whatever builds. so it is safe to use to guarantee
|
|
||||||
/// parameter evaluation.
|
|
||||||
inline void
|
|
||||||
ignore (void) noexcept
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
void
|
|
||||||
ignore (T, const Args&...) noexcept
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
/// query the index of the first occurrence of type `T' in the tuple type
|
|
||||||
/// `TupleT'.
|
|
||||||
///
|
|
||||||
/// if the query type does not occur in the tuple type a compiler error
|
|
||||||
/// should be generated.
|
|
||||||
template <class T, class TupleT>
|
|
||||||
struct index;
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <class T, class ...Types>
|
|
||||||
struct index<T, std::tuple<T, Types...>> {
|
|
||||||
static constexpr std::size_t value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <class T, class U, class ...Types>
|
|
||||||
struct index<T,std::tuple<U, Types...>> {
|
|
||||||
static constexpr std::size_t value = 1 + index<T, std::tuple<Types...>>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t IndexV, typename HeadT, typename ...TailT>
|
|
||||||
auto
|
|
||||||
get (HeadT &&head, TailT &&...tail)
|
|
||||||
{
|
|
||||||
if constexpr (IndexV == 0)
|
|
||||||
return std::forward<HeadT> (head);
|
|
||||||
else
|
|
||||||
return get<IndexV-1> (std::forward<TailT> (tail)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <std::size_t Idx, typename ...Args>
|
|
||||||
auto
|
|
||||||
nth (Args &&...args)
|
|
||||||
{
|
|
||||||
return std::get<Idx> (std::tuple {std::forward<Args> (args)...});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
162
tuple/type.hpp
Normal file
162
tuple/type.hpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRUFT_UTIL_TUPLE_TYPE_HPP
|
||||||
|
#define CRUFT_UTIL_TUPLE_TYPE_HPP
|
||||||
|
|
||||||
|
#include "../types.hpp"
|
||||||
|
|
||||||
|
#include "../types/traits.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
|
||||||
|
namespace util::tuple::type {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
/// call a provided FunctorT with type_tag<T> for each type in the
|
||||||
|
/// tuple-like type TupleT.
|
||||||
|
template<
|
||||||
|
typename TupleT,
|
||||||
|
typename FunctorT,
|
||||||
|
size_t S = 0
|
||||||
|
>
|
||||||
|
void
|
||||||
|
each (FunctorT &&func)
|
||||||
|
{
|
||||||
|
static_assert (S < std::tuple_size_v<TupleT>);
|
||||||
|
using value_type = typename std::tuple_element<S,TupleT>::type;
|
||||||
|
|
||||||
|
func (util::type_tag<value_type> {});
|
||||||
|
|
||||||
|
if constexpr (S + 1 < std::tuple_size_v<TupleT>) {
|
||||||
|
each<TupleT,FunctorT,S+1> (std::forward<FunctorT> (func));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Statically map the member types of a tuple via F<>::type
|
||||||
|
///
|
||||||
|
/// TupleT: tuple type
|
||||||
|
/// FieldT: type mapping object, conversion uses FieldT<>::type
|
||||||
|
/// Indices: tuple indexing helper
|
||||||
|
template <
|
||||||
|
typename TupleT,
|
||||||
|
template <
|
||||||
|
typename
|
||||||
|
> class FieldT,
|
||||||
|
typename Indices = std::make_index_sequence<
|
||||||
|
std::tuple_size<TupleT>::value
|
||||||
|
>
|
||||||
|
>
|
||||||
|
struct map;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
typename TupleT,
|
||||||
|
template <
|
||||||
|
typename
|
||||||
|
> class FieldT,
|
||||||
|
size_t ...Indices
|
||||||
|
>
|
||||||
|
struct map<
|
||||||
|
TupleT,
|
||||||
|
FieldT,
|
||||||
|
std::index_sequence<Indices...>
|
||||||
|
> {
|
||||||
|
typedef std::tuple<
|
||||||
|
typename FieldT<
|
||||||
|
typename std::tuple_element<Indices, TupleT>::type
|
||||||
|
>::type...
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
/// query the index of the first occurrence of type `T' in the tuple-like
|
||||||
|
/// type `TupleT'.
|
||||||
|
///
|
||||||
|
/// if the query type does not occur in the tuple type a compiler error
|
||||||
|
/// should be generated.
|
||||||
|
template<
|
||||||
|
typename TupleT,
|
||||||
|
typename ValueT,
|
||||||
|
typename = std::make_index_sequence<
|
||||||
|
std::tuple_size_v<TupleT>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
struct index { };
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// specialisation for tuples with matching first elements. the index is 0.
|
||||||
|
template<
|
||||||
|
typename ValueT,
|
||||||
|
typename ...TailT,
|
||||||
|
size_t ...Indices
|
||||||
|
>
|
||||||
|
struct index<
|
||||||
|
std::tuple<ValueT, TailT...>,
|
||||||
|
ValueT,
|
||||||
|
std::index_sequence<Indices...>
|
||||||
|
> {
|
||||||
|
static constexpr std::size_t value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// specialisation for tuples with non-matching first elements.
|
||||||
|
// increment and recurse.
|
||||||
|
template<
|
||||||
|
typename ValueT,
|
||||||
|
typename HeadT,
|
||||||
|
typename ...TailT,
|
||||||
|
size_t ...Indices
|
||||||
|
>
|
||||||
|
struct index<
|
||||||
|
std::tuple<HeadT, TailT...>,
|
||||||
|
ValueT,
|
||||||
|
std::index_sequence<Indices...>
|
||||||
|
> {
|
||||||
|
static constexpr std::size_t value = 1u + index<std::tuple<TailT...>,ValueT>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// convert the tuple type (which is not a tuple or it would have matched
|
||||||
|
// the tuple specialisation, into the equivalent std::tuple and requery
|
||||||
|
// against that.
|
||||||
|
template <
|
||||||
|
typename TupleT,
|
||||||
|
typename ValueT,
|
||||||
|
size_t ...Indices
|
||||||
|
> struct index<
|
||||||
|
TupleT,
|
||||||
|
ValueT,
|
||||||
|
std::index_sequence<Indices...>
|
||||||
|
> {
|
||||||
|
static constexpr std::size_t value = index<
|
||||||
|
std::tuple<std::tuple_element_t<Indices,TupleT>...>,
|
||||||
|
ValueT,
|
||||||
|
std::index_sequence<Indices...>
|
||||||
|
>::value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
75
tuple/value.hpp
Normal file
75
tuple/value.hpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRUFT_UTIL_TUPLE_VALUE_HPP
|
||||||
|
#define CRUFT_UTIL_TUPLE_VALUE_HPP
|
||||||
|
|
||||||
|
#include "../types.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
namespace util::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>);
|
||||||
|
|
||||||
|
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))...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -14,13 +14,14 @@
|
|||||||
* Copyright 2011-2014 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2014 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_TYPES_HPP
|
#ifndef CRUFT_UTIL_TYPES_HPP
|
||||||
#define __UTIL_TYPES_HPP
|
#define CRUFT_UTIL_TYPES_HPP
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
50
variadic.hpp
50
variadic.hpp
@ -11,25 +11,49 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2017 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2017-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_VARIADIC_HPP
|
#ifndef CRUFT_UTIL_VARIADIC_HPP
|
||||||
#define __UTIL_VARIADIC_HPP
|
#define CRUFT_UTIL_VARIADIC_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
namespace util::variadic {
|
namespace util::variadic {
|
||||||
/// return a reference to the first item in a parameter pack
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, typename ...Tail>
|
/// do nothing with a set of parameters.
|
||||||
T&
|
///
|
||||||
first (T &t, Tail&&...)
|
/// useful for temporarily silencing unused argument warnings in parameter
|
||||||
{ return t; }
|
/// packs, or for avoiding assignment of [[gnu::warn_unused_result]] to a
|
||||||
|
/// temporary value we'd just cast to void anyway (GCC#66425).
|
||||||
|
///
|
||||||
|
/// it is guaranteed that this function will never be defined out in
|
||||||
|
/// debug/release/whatever builds. so it is safe to use to guarantee
|
||||||
|
/// parameter evaluation.
|
||||||
|
template <typename ...Args>
|
||||||
|
void
|
||||||
|
ignore (const Args&...) noexcept ((std::is_nothrow_destructible_v<Args> && ...))
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
/// return a reference to the first item in a const parameter pack
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, typename ...Tail>
|
/// Returns the argument at index `IndexV', as if we called:
|
||||||
const T&
|
/// std::get<N> (std::make_tuple (...))
|
||||||
first (const T &t, const Tail&&...)
|
template <std::size_t IndexV, typename HeadT, typename ...TailT>
|
||||||
{ return t; }
|
auto
|
||||||
|
get (HeadT &&head, TailT &&...tail) noexcept ((std::is_nothrow_move_constructible_v<TailT> && ...))
|
||||||
|
{
|
||||||
|
static_assert (IndexV < sizeof... (TailT) + 1, "Index is out of bounds");
|
||||||
|
|
||||||
|
if constexpr (IndexV == 0)
|
||||||
|
return std::forward<HeadT> (head);
|
||||||
|
else
|
||||||
|
return get<IndexV-1> (std::forward<TailT> (tail)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user