Program Listing for File tuple.hpp
↰ Return to documentation for file (/tmp/ws/src/proxsuite/include/proxsuite/linalg/veg/tuple.hpp
)
#ifndef VEG_TUPLE_HPP_B8PHUNWES
#define VEG_TUPLE_HPP_B8PHUNWES
#include "proxsuite/linalg/veg/type_traits/assignable.hpp"
#include "proxsuite/linalg/veg/internal/dbg.hpp"
#include "proxsuite/linalg/veg/type_traits/invocable.hpp"
#include "proxsuite/linalg/veg/util/get.hpp"
#include "proxsuite/linalg/veg/internal/fix_index.hpp"
#include "proxsuite/linalg/veg/internal/prologue.hpp"
#if defined(__GLIBCXX__)
namespace std /* NOLINT */ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename T>
struct tuple_size;
template<::proxsuite::linalg::veg::usize, typename T>
struct tuple_element;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#else
#include <utility> // std::tuple_{size,element}
#endif
/******************************************************************************/
#define __VEG_IMPL_BIND(I, Tuple, Identifier) /* NOLINT */ \
auto&& Identifier /* NOLINT */ = \
::proxsuite::linalg::veg::nb::get<I>{}(VEG_FWD(Tuple));
#define __VEG_IMPL_BIND_ID_SEQ(/* NOLINT */ \
CV_Auto, \
Identifiers, \
Tuple, \
Tuple_Size, \
TupleId) \
CV_Auto TupleId = Tuple; \
static_assert( \
::std::tuple_size<typename ::proxsuite::linalg::veg::meta::uncvref_t< \
decltype(TupleId)>>::value == (Tuple_Size), \
"wrong number of identifiers"); \
__VEG_PP_TUPLE_FOR_EACH_I(__VEG_IMPL_BIND, TupleId, Identifiers) \
VEG_NOM_SEMICOLON
// example: difference vs c++17 structure bindings
// auto get() -> tuple<A, B&, C&&>;
//
// auto [a, b, c] = get();
// VEG_BIND(auto, (x, y, z), get());
// decltype({a,b,c}) => {A,B&,C&&} same as tuple_element<i, E>
// decltype({x,y,z}) => {A&&,B&,C&&} always a reference, lvalue if initializer
// expression or tuple_element<i, E> is an
// lvalue, rvalue otherwise.
//
#define VEG_BIND(CV_Auto, Identifiers, Tuple) \
__VEG_IMPL_BIND_ID_SEQ(CV_Auto, \
Identifiers, \
Tuple, \
__VEG_PP_TUPLE_SIZE(Identifiers), \
__VEG_PP_CAT(_dummy_tuple_variable_id_, __LINE__))
/******************************************************************************/
namespace proxsuite {
namespace linalg {
namespace veg {
template<typename T, usize I>
using inner_ith = decltype(VEG_DECLVAL(T)[Fix<isize{ I }>{}]);
template<typename... Ts>
struct Tuple;
namespace tuple {
namespace nb {
struct tuplify
{
template<typename... Ts>
VEG_NODISCARD VEG_INLINE constexpr auto operator()(Ts... args) const
VEG_NOEXCEPT->proxsuite::linalg::veg::Tuple<Ts...>
{
return { tuplify{}, Ts(VEG_FWD(args))... };
}
};
} // namespace nb
VEG_NIEBLOID(tuplify);
} // namespace tuple
inline namespace tags {
using Tuplify = tuple::nb::tuplify;
using tuple::tuplify;
} // namespace tags
namespace tuple {
using proxsuite::linalg::veg::Tuple;
} // namespace tuple
namespace tuple {
template<typename ISeq, typename... Ts>
struct IndexedTuple
{};
#if VEG_HAS_NO_UNIQUE_ADDRESS
#define __VEG_IMPL_LEAF(Tuple, I, ...) /* NOLINT */ \
(static_cast< \
::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__> const&>( \
(Tuple).inner) \
.leaf)
#define __VEG_IMPL_LEAF_MUT(Tuple, I, ...) /* NOLINT */ \
(static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__>&>( \
(Tuple).inner) \
.leaf)
#define __VEG_IMPL_LEAF_ONCE(Tuple, I, ...) /* NOLINT */ \
(static_cast<__VA_ARGS__&&>( \
static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__>&&>( \
(Tuple).inner) \
.leaf))
template<usize I, typename T>
struct TupleLeaf
{
VEG_NO_UNIQUE_ADDRESS T leaf;
};
#else
#define __VEG_IMPL_LEAF(Tuple, I, ...) /* NOLINT */ \
(static_cast<__VA_ARGS__ const&>( \
static_cast< \
::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__> const&>( \
(Tuple).inner) \
.leaf_get()))
#define __VEG_IMPL_LEAF_MUT(Tuple, I, ...) /* NOLINT */ \
(static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__>&>( \
(Tuple).inner) \
.leaf_get())
#define __VEG_IMPL_LEAF_ONCE(Tuple, I, ...) /* NOLINT */ \
(static_cast<__VA_ARGS__&&>( \
static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf<I, __VA_ARGS__>&&>( \
(Tuple).inner) \
.leaf_get()))
template<typename T, bool = (VEG_CONCEPT(empty<T>) && !VEG_CONCEPT(final<T>))>
struct TupleLeafImpl;
template<typename T>
struct TupleLeafImpl<T, true> : T
{
template<typename Fn>
VEG_INLINE constexpr TupleLeafImpl(InPlace<void> /*tag*/, Fn fn)
VEG_NOEXCEPT_LIKE(VEG_FWD(fn)())
: T{ VEG_FWD(fn)() }
{
}
TupleLeafImpl() = default;
VEG_INLINE constexpr auto leaf_get() const VEG_NOEXCEPT->T&
{
return const_cast<T&>(static_cast<T const&>(*this));
}
};
template<typename T>
struct TupleLeafImpl<T, false>
{
T leaf;
template<typename Fn>
VEG_INLINE constexpr TupleLeafImpl(InPlace<void> /*tag*/, Fn fn)
VEG_NOEXCEPT_LIKE(VEG_FWD(fn)())
: leaf{ VEG_FWD(fn)() }
{
}
TupleLeafImpl() = default;
VEG_INLINE constexpr auto leaf_get() const VEG_NOEXCEPT->T&
{
return const_cast<T&>(leaf);
}
};
template<usize I, typename T>
struct TupleLeaf : TupleLeafImpl<T>
{
using TupleLeafImpl<T>::TupleLeafImpl;
};
#endif
namespace nb {
struct unpack
{
VEG_TEMPLATE(
(typename Fn, typename... Ts, usize... Is),
requires(VEG_CONCEPT(
fn_once<Fn,
proxsuite::linalg::veg::meta::invoke_result_t<Fn, Ts&&...>,
Ts&&...>)),
VEG_INLINE constexpr auto
operator(),
(args,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&&),
(fn, Fn))
const VEG_NOEXCEPT_IF(
VEG_CONCEPT(nothrow_fn_once<
Fn,
proxsuite::linalg::veg::meta::invoke_result_t<Fn, Ts&&...>,
Ts&&...>))
->proxsuite::linalg::veg::meta::invoke_result_t<Fn, Ts&&...>
{
return VEG_FWD(fn)(__VEG_IMPL_LEAF_ONCE(args, Is, Ts)...);
}
};
struct for_each_i
{
VEG_TEMPLATE(
(typename Fn, typename... Ts, usize... Is),
requires(VEG_ALL_OF(VEG_CONCEPT(fn_once<inner_ith<Fn&, Is>, void, Ts>))),
VEG_INLINE VEG_CPP14(constexpr) void
operator(),
(args,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&&),
(fn, Fn))
const VEG_NOEXCEPT_IF(
VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once<inner_ith<Fn, Is>, void, Ts>)))
{
VEG_EVAL_ALL(fn[Fix<isize{ Is }>{}](__VEG_IMPL_LEAF_ONCE(args, Is, Ts)));
}
};
struct for_each
{
VEG_TEMPLATE(
(typename Fn, typename... Ts, usize... Is),
requires(VEG_ALL_OF(VEG_CONCEPT(fn_mut<Fn, void, Ts&&>))),
VEG_INLINE VEG_CPP14(constexpr) void
operator(),
(args,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&&),
(fn, Fn))
const VEG_NOEXCEPT_IF(VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_mut<Fn, void, Ts&&>)))
{
VEG_EVAL_ALL(fn(__VEG_IMPL_LEAF_ONCE(args, Is, Ts)));
}
};
struct map_i
{
VEG_TEMPLATE(
(typename Fn, typename... Ts, usize... Is),
requires(VEG_ALL_OF(VEG_CONCEPT(
fn_once< //
inner_ith<Fn&, Is>,
proxsuite::linalg::veg::meta::invoke_result_t<inner_ith<Fn&, Is>, Ts>,
Ts>))),
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto
operator(),
(args,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&&),
(fn, Fn))
const VEG_NOEXCEPT_IF(
VEG_ALL_OF(VEG_CONCEPT(
nothrow_fn_once< //
inner_ith<Fn&, Is>,
proxsuite::linalg::veg::meta::invoke_result_t<inner_ith<Fn&, Is>, Ts>,
Ts>)))
->Tuple<
proxsuite::linalg::veg::meta::invoke_result_t<inner_ith<Fn&, Is>, Ts>...>
{
return { inplace[tuplify{}],
_detail::WithArg<inner_ith<Fn&, Is>, Ts>{
fn[Fix<isize{ Is }>{}],
__VEG_IMPL_LEAF_ONCE(args, Is, Ts) }... };
}
};
struct map
{
VEG_TEMPLATE(
(typename Fn, typename... Ts, usize... Is),
requires(VEG_ALL_OF(VEG_CONCEPT(
fn_mut<Fn,
proxsuite::linalg::veg::meta::invoke_result_t<Fn&, Ts&&>,
Ts&&>))),
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto
operator(),
(args,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&&),
(fn, Fn))
const VEG_NOEXCEPT_IF(
VEG_ALL_OF(VEG_CONCEPT(
nothrow_fn_mut<Fn,
proxsuite::linalg::veg::meta::invoke_result_t<Fn&, Ts&&>,
Ts&&>)))
->Tuple<proxsuite::linalg::veg::meta::invoke_result_t<Fn&, Ts&&>...>
{
return {
inplace[tuplify{}],
_detail::WithArg<Fn&, Ts&&>{
fn,
__VEG_IMPL_LEAF_ONCE(args, Is, Ts),
}...,
};
}
};
} // namespace nb
template<usize... Is, typename... Ts>
struct IndexedTuple<meta::index_sequence<Is...>, Ts...>
{
struct _ : TupleLeaf<Is, Ts>...
{
#if !defined(VEG_WITH_CXX17_SUPPORT)
#if VEG_HAS_NO_UNIQUE_ADDRESS
template<typename... Fns>
VEG_INLINE constexpr _(InPlace<void> /* unused */, Fns... fns) noexcept(
VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once<Fns, Ts>)))
: TupleLeaf<Is, Ts>{ VEG_FWD(fns)() }...
{
}
#else
template<typename... Fns>
VEG_INLINE constexpr _(InPlace<void> /*unused*/, Fns... fns) noexcept(
VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once<Fns, Ts>)))
: TupleLeaf<Is, Ts>{ inplace, VEG_FWD(fns) }...
{
}
#endif
_() = default;
#endif
} inner;
IndexedTuple() = default;
VEG_INLINE constexpr IndexedTuple(Tuplify /*tag*/, Ts... args) VEG_NOEXCEPT
: inner
{
#if !defined(VEG_WITH_CXX17_SUPPORT)
inplace, _detail::MoveFn<Ts>{ VEG_FWD(args) }...,
#else
#if VEG_HAS_NO_UNIQUE_ADDRESS
TupleLeaf<Is, Ts>{ Ts(VEG_FWD(args)) }...
#else
TupleLeaf<Is, Ts>{ inplace, _detail::MoveFn<Ts>{ VEG_FWD(args) } }...
#endif
#endif
}
{
}
VEG_TEMPLATE((typename _, typename... Fns),
requires(VEG_CONCEPT(same<_, Tuplify>) &&
VEG_ALL_OF(VEG_CONCEPT(fn_once<Fns, Ts>))),
VEG_INLINE constexpr IndexedTuple,
(/*tag*/, InPlace<_>),
(... fns, Fns))
VEG_NOEXCEPT_IF(VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once<Fns, Ts>)))
: inner
{
#if !defined(VEG_WITH_CXX17_SUPPORT)
inplace, VEG_FWD(fns)...
#else
#if VEG_HAS_NO_UNIQUE_ADDRESS
TupleLeaf<Is, Ts>{ VEG_FWD(fns)() }...
#else
TupleLeaf<Is, Ts>{ inplace, VEG_FWD(fns) }...
#endif
#endif
}
{
}
VEG_EXPLICIT_COPY(IndexedTuple);
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto as_ref() const
& VEG_NOEXCEPT->Tuple<Ref<Ts>...>
{
return {
tuplify,
ref(__VEG_IMPL_LEAF(*this, Is, Ts))...,
};
}
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto as_mut()
VEG_NOEXCEPT->Tuple<RefMut<Ts>...>
{
return {
tuplify,
mut(__VEG_IMPL_LEAF_MUT(*this, Is, Ts))...,
};
}
template<isize I>
void operator[](Fix<I> /*arg*/) const&& = delete;
VEG_TEMPLATE((isize I),
requires(static_cast<usize>(I) < sizeof...(Ts)),
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto
operator[],
(/*arg*/, Fix<I>)) &&
VEG_NOEXCEPT_IF(
VEG_CONCEPT(nothrow_movable<ith<static_cast<usize>(I), Ts...>>))
-> ith<static_cast<usize>(I), Ts...>
{
return __VEG_IMPL_LEAF_ONCE(
*this, static_cast<usize>(I), ith<static_cast<usize>(I), Ts...>);
}
VEG_TEMPLATE((isize I),
requires(static_cast<usize>(I) < sizeof...(Ts)),
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto
operator[],
(/*arg*/, Fix<I>)) &
VEG_NOEXCEPT->ith<static_cast<usize>(I), Ts...>&
{
return __VEG_IMPL_LEAF_MUT(
*this, static_cast<usize>(I), ith<static_cast<usize>(I), Ts...>);
}
VEG_TEMPLATE((isize I),
requires(static_cast<usize>(I) < sizeof...(Ts)),
VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto
operator[],
(/*arg*/, Fix<I>))
const & VEG_NOEXCEPT->ith<static_cast<usize>(I), Ts...> const&
{
return __VEG_IMPL_LEAF(
*this, static_cast<usize>(I), ith<static_cast<usize>(I), Ts...>);
}
};
} // namespace tuple
namespace _detail {
namespace meta_ {
struct NonTupleBaseInfoImpl
{
static constexpr bool is_tuple = false;
static constexpr usize size = 0;
template<usize I>
using ith = void;
using seq = void;
};
template<typename... Ts>
struct TupleBaseInfoImpl
{
static constexpr bool is_tuple = true;
static constexpr usize size = sizeof...(Ts);
template<usize I>
using ith = proxsuite::linalg::veg::ith<I, Ts...>;
using seq = meta::type_sequence<Ts...>;
using Tuple = proxsuite::linalg::veg::Tuple<Ts...>;
using IndexedTuple = proxsuite::linalg::veg::tuple::
IndexedTuple<meta::make_index_sequence<sizeof...(Ts)>, Ts...>;
};
struct is_tuple_helper
{
static auto test(void*) -> NonTupleBaseInfoImpl;
template<usize... Is, typename... Ts>
static auto test(tuple::IndexedTuple<meta::index_sequence<Is...>, Ts...>*)
-> TupleBaseInfoImpl<Ts...>;
};
template<typename T>
struct IndexedToTuple;
template<usize... Is, typename... Ts>
struct IndexedToTuple<tuple::IndexedTuple<meta::index_sequence<Is...>, Ts...>>
{
using Type = Tuple<Ts...>;
};
} // namespace meta_
} // namespace _detail
namespace tuple {
namespace meta {
template<typename T>
using TupleBaseInfo =
decltype(_detail::meta_::is_tuple_helper::test(static_cast<T*>(nullptr)));
template<typename T>
using is_tuple =
proxsuite::linalg::veg::meta::bool_constant<TupleBaseInfo<T>::is_tuple>;
template<typename T>
using tuple_size =
proxsuite::linalg::veg::meta::constant<usize, TupleBaseInfo<T>::size>;
template<usize I, typename T>
using tuple_element = typename TupleBaseInfo<T>::template ith<I>;
} // namespace meta
} // namespace tuple
namespace concepts {
namespace tuple {
VEG_DEF_CONCEPT(typename T,
tuple,
proxsuite::linalg::veg::tuple::meta::is_tuple<T>::value);
} // namespace tuple
} // namespace concepts
template<typename... Ts>
struct Tuple
: tuple::IndexedTuple<meta::make_index_sequence<sizeof...(Ts)>, Ts...>
{
using Indexed =
tuple::IndexedTuple<meta::make_index_sequence<sizeof...(Ts)>, Ts...>;
using Indexed::Indexed;
VEG_EXPLICIT_COPY(Tuple);
};
VEG_CPP17(template<typename... Ts> Tuple(Tuplify, Ts...) -> Tuple<Ts...>;)
namespace tuple {
template<usize I, usize... Is, typename... Ts>
VEG_NODISCARD VEG_INLINE constexpr auto
get(tuple::IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...> const& tup) VEG_NOEXCEPT->ith<I, Ts...> const&
{
return __VEG_IMPL_LEAF(tup, I, ith<I, Ts...>);
}
template<usize I, usize... Is, typename... Ts>
VEG_NODISCARD VEG_INLINE constexpr auto
get(tuple::IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>& tup) VEG_NOEXCEPT->ith<I, Ts...>&
{
return __VEG_IMPL_LEAF_MUT(tup, I, ith<I, Ts...>);
}
template<usize I, usize... Is, typename... Ts>
VEG_NODISCARD VEG_INLINE constexpr auto
get(tuple::IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...> const&& tup) VEG_NOEXCEPT->ith<I, Ts...> const&&
{
return static_cast<ith<I, Ts...> const&&>(
__VEG_IMPL_LEAF(tup, I, ith<I, Ts...>));
}
template<usize I, usize... Is, typename... Ts>
VEG_NODISCARD VEG_INLINE constexpr auto
get(tuple::IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ts...>&& tup) VEG_NOEXCEPT->ith<I, Ts...>&&
{
return __VEG_IMPL_LEAF_ONCE(tup, I, ith<I, Ts...>);
}
} // namespace tuple
namespace _detail {
namespace _tuple {
template<usize... Is, typename... Ts>
VEG_INLINE static constexpr auto
tuple_fwd(tuple::IndexedTuple<meta::index_sequence<Is...>, Ts...>&& tup)
VEG_NOEXCEPT->Tuple<Ts&&...>
{
return {
((void)(tup), tuplify),
__VEG_IMPL_LEAF_ONCE(tup, Is, Ts)...,
};
}
} // namespace _tuple
} // namespace _detail
namespace tuple {
namespace nb {
struct with
{
VEG_TEMPLATE(
typename... Fns,
requires(VEG_ALL_OF(VEG_CONCEPT(
fn_once<Fns, proxsuite::linalg::veg::meta::invoke_result_t<Fns>>))),
VEG_NODISCARD VEG_INLINE constexpr auto
operator(),
(... args, Fns))
const VEG_NOEXCEPT_IF(
VEG_ALL_OF(VEG_CONCEPT(
nothrow_fn_once<Fns,
proxsuite::linalg::veg::meta::invoke_result_t<Fns>>)))
->proxsuite::linalg::veg::Tuple<
proxsuite::linalg::veg::meta::invoke_result_t<Fns>...>
{
return { inplace[tuplify{}], VEG_FWD(args)... };
}
};
struct zip
{
template<typename... Tuples>
using PreZip =
proxsuite::linalg::veg::meta::type_sequence_zip<Tuple, Tuples...>;
template<typename... Tuples>
using Zip = proxsuite::linalg::veg::meta::
detected_t<PreZip, typename meta::TupleBaseInfo<Tuples>::Tuple...>;
VEG_TEMPLATE(
(typename... Tuples),
requires(VEG_ALL_OF(VEG_CONCEPT(tuple::tuple<Tuples>)) &&
VEG_CONCEPT(all_same<tuple::meta::tuple_size<Tuples>...>)),
VEG_NODISCARD VEG_INLINE constexpr auto
operator(),
(... tups, Tuples))
const VEG_NOEXCEPT->Zip<Tuples...>
{
return zip::apply(
static_cast<typename meta::TupleBaseInfo<Tuples>::IndexedTuple&&>(
tups)...);
}
private:
template<typename... Tuples>
VEG_INLINE static constexpr auto pre_apply(
proxsuite::linalg::veg::meta::true_type /*unused*/,
Tuples&&... tups) VEG_NOEXCEPT->Zip<Tuples...>
{
return zip::apply(VEG_FWD(tups)...);
}
template<typename... Tuples>
VEG_INLINE static constexpr auto pre_apply(
proxsuite::linalg::veg::meta::false_type /*unused*/,
Tuples&&... tups) VEG_NOEXCEPT->Zip<Tuples...>
{
return zip::from_ref_to_result(
Tag<proxsuite::linalg::veg::meta::type_sequence_zip<
Tuple,
typename _detail::meta_::IndexedToTuple<Tuples>::Type...>>{},
zip::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...));
}
VEG_INLINE static auto apply() VEG_NOEXCEPT->Tuple<> { return {}; }
template<usize I, typename T>
struct Helper
{
template<typename... Ts>
using Type = Tuple<T, meta::tuple_element<I, Ts>...>;
template<typename... Ts>
VEG_INLINE constexpr auto apply(Ts&&... tups) const
VEG_NOEXCEPT->Type<Ts...>
{
return {
tuplify{},
VEG_FWD(first),
__VEG_IMPL_LEAF_ONCE(tups, I, meta::tuple_element<I, Ts>)...,
};
}
T&& first;
};
template<usize... Is, typename... Ts, typename... Tuples>
VEG_INLINE static constexpr auto apply(
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>, Ts...>
first,
Tuples... rest) VEG_NOEXCEPT->Tuple< //
typename Helper<Is, Ts>:: //
template Type<Tuples...>...>
{
return {
((void)first, tuplify{}),
Helper<Is, Ts>{ __VEG_IMPL_LEAF_ONCE(first, Is, Ts) }
.template apply<Tuples...>(VEG_FWD(rest)...)...,
};
}
template<typename ISeq, typename... InnerTargets>
struct ConverterImpl;
template<typename OuterTarget>
struct Converter;
template<usize... Is, typename... InnerTargets>
struct ConverterImpl<proxsuite::linalg::veg::meta::index_sequence<Is...>,
InnerTargets...>
{
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
InnerTargets&&...>&& refs;
VEG_INLINE constexpr auto operator()() const
&& VEG_NOEXCEPT->Tuple<InnerTargets...>
{
return {
inplace[tuplify{}],
_detail::MoveFn<InnerTargets>{
__VEG_IMPL_LEAF_ONCE(refs, Is, InnerTargets) }...,
};
}
};
template<typename... InnerTargets>
struct Converter<Tuple<InnerTargets...>>
{
using Type =
ConverterImpl<proxsuite::linalg::veg::meta::make_index_sequence<sizeof...(
InnerTargets)>,
InnerTargets...>;
};
template<usize... Is, typename... Tups, typename... OuterTargets>
VEG_INLINE static constexpr auto from_ref_to_result(
Tag<Tuple<OuterTargets...>> /*tag*/,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>, Tups...>
zipped_refs) VEG_NOEXCEPT->Tuple<OuterTargets...>
{
return {
((void)zipped_refs, inplace[tuplify{}]),
typename Converter<OuterTargets>::Type{
__VEG_IMPL_LEAF_ONCE(zipped_refs, Is, Tups),
}...,
};
}
};
struct cat
{
template<typename... Tuples>
using PreConcat =
proxsuite::linalg::veg::meta::type_sequence_cat<Tuple, Tuples...>;
template<typename... Tuples>
using Concat = proxsuite::linalg::veg::meta::
detected_t<PreConcat, typename meta::TupleBaseInfo<Tuples>::Tuple...>;
VEG_TEMPLATE((typename... Tuples),
requires(VEG_ALL_OF(VEG_CONCEPT(tuple::tuple<Tuples>))),
VEG_NODISCARD VEG_INLINE constexpr auto
operator(),
(... tups, Tuples))
const VEG_NOEXCEPT->Concat<Tuples...>
{
return cat::apply(
static_cast<typename meta::TupleBaseInfo<Tuples>::IndexedTuple&&>(
tups)...);
}
private:
template<typename... Tuples>
VEG_INLINE static constexpr auto pre_apply(
proxsuite::linalg::veg::meta::true_type /*unused*/,
Tuples&&... tups) VEG_NOEXCEPT->Concat<Tuples...>
{
return cat::apply(VEG_FWD(tups)...);
}
template<typename... Tuples>
VEG_INLINE static constexpr auto pre_apply(
proxsuite::linalg::veg::meta::false_type /*unused*/,
Tuples&&... tups) VEG_NOEXCEPT->Concat<Tuples...>
{
return cat::template from_ref_to_result(
Tag<proxsuite::linalg::veg::meta::type_sequence_cat<Tuple, Tuples...>>{},
cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...));
}
template<typename... Targets, usize... Is, typename... Refs>
VEG_INLINE static constexpr auto from_ref_to_result(
Tag<Tuple<Targets...>> /*tag*/,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>, Refs...>
refs) VEG_NOEXCEPT->proxsuite::linalg::veg::Tuple<Targets...>
{
return {
inplace[tuplify{}],
_detail::MoveFn<Targets>{ __VEG_IMPL_LEAF_ONCE(refs, Is, Targets) }...,
};
}
VEG_INLINE static auto apply() VEG_NOEXCEPT->Tuple<> { return {}; }
template<usize... Is, typename... Ts, typename... Tuples>
VEG_INLINE static constexpr auto apply(
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>, Ts...>&&
first,
Tuples&&... rest)
VEG_NOEXCEPT->proxsuite::linalg::veg::meta::type_sequence_cat<
Tuple,
Tuple<Ts...>,
typename _detail::meta_::IndexedToTuple<Tuples>::Type...>
{
return cat::apply2(VEG_FWD(first), cat::apply(VEG_FWD(rest)...));
}
template<usize... Is, typename... Ts, usize... Js, typename... Us>
VEG_INLINE static constexpr auto apply2(
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>, Ts...>&&
first,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Js...>, Us...>&&
second) VEG_NOEXCEPT->Tuple<Ts..., Us...>
{
return {
tuplify{},
__VEG_IMPL_LEAF_ONCE(first, Is, Ts)...,
__VEG_IMPL_LEAF_ONCE(second, Js, Us)...,
};
}
};
struct deref_assign
{
VEG_TEMPLATE(
(typename... Ts, typename... Us, usize... Is),
requires(VEG_ALL_OF(VEG_CONCEPT(assignable<Ts&, Us const&>))),
VEG_INLINE VEG_CPP14(constexpr) void
operator(),
(ts,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
RefMut<Ts>...>),
(us,
IndexedTuple<proxsuite::linalg::veg::meta::index_sequence<Is...>,
Ref<Us>...>))
const VEG_NOEXCEPT_IF(
VEG_ALL_OF(VEG_CONCEPT(nothrow_assignable<Ts&, Us const&>)))
{
VEG_EVAL_ALL(__VEG_IMPL_LEAF_MUT(ts, Is, RefMut<Ts>).get() =
__VEG_IMPL_LEAF(us, Is, Ref<Us>).get());
}
};
} // namespace nb
VEG_NIEBLOID(with);
VEG_NIEBLOID(zip);
VEG_NIEBLOID(cat);
VEG_NIEBLOID(unpack);
VEG_NIEBLOID(for_each);
VEG_NIEBLOID(for_each_i);
VEG_NIEBLOID(map);
VEG_NIEBLOID(map_i);
VEG_NIEBLOID(deref_assign);
} // namespace tuple
namespace cpo {
template<usize... Is, typename... Ts>
struct is_trivially_relocatable<
tuple::IndexedTuple<meta::index_sequence<Is...>, Ts...>>
: meta::bool_constant<(VEG_ALL_OF(is_trivially_relocatable<Ts>::value))>
{};
template<usize... Is, typename... Ts>
struct is_trivially_constructible<
tuple::IndexedTuple<meta::index_sequence<Is...>, Ts...>>
: meta::bool_constant<(VEG_ALL_OF(is_trivially_constructible<Ts>::value))>
{};
template<typename... Ts>
struct is_trivially_relocatable<tuple::Tuple<Ts...>>
: meta::bool_constant<(VEG_ALL_OF(is_trivially_relocatable<Ts>::value))>
{};
template<typename... Ts>
struct is_trivially_constructible<tuple::Tuple<Ts...>>
: meta::bool_constant<(VEG_ALL_OF(is_trivially_constructible<Ts>::value))>
{};
} // namespace cpo
} // namespace veg
} // namespace linalg
} // namespace proxsuite
template<typename... Ts>
struct std::tuple_size<proxsuite::linalg::veg::Tuple<Ts...>>
: ::proxsuite::linalg::veg::meta::constant<proxsuite::linalg::veg::usize,
sizeof...(Ts)>
{};
template<proxsuite::linalg::veg::usize I, typename... Ts>
struct std::tuple_element<I, proxsuite::linalg::veg::Tuple<Ts...>>
{
using type = proxsuite::linalg::veg::ith<I, Ts...>;
};
#include "proxsuite/linalg/veg/internal/epilogue.hpp"
#endif /* end of include guard VEG_TUPLE_HPP_B8PHUNWES */