.. _program_listing_file__tmp_ws_src_proxsuite_include_proxsuite_linalg_veg_tuple.hpp: Program Listing for File tuple.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/proxsuite/include/proxsuite/linalg/veg/tuple.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #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 struct tuple_size; template<::proxsuite::linalg::veg::usize, typename T> struct tuple_element; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #else #include // std::tuple_{size,element} #endif /******************************************************************************/ #define __VEG_IMPL_BIND(I, Tuple, Identifier) /* NOLINT */ \ auto&& Identifier /* NOLINT */ = \ ::proxsuite::linalg::veg::nb::get{}(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>::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; // // auto [a, b, c] = get(); // VEG_BIND(auto, (x, y, z), get()); // decltype({a,b,c}) => {A,B&,C&&} same as tuple_element // decltype({x,y,z}) => {A&&,B&,C&&} always a reference, lvalue if initializer // expression or tuple_element 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 using inner_ith = decltype(VEG_DECLVAL(T)[Fix{}]); template struct Tuple; namespace tuple { namespace nb { struct tuplify { template VEG_NODISCARD VEG_INLINE constexpr auto operator()(Ts... args) const VEG_NOEXCEPT->proxsuite::linalg::veg::Tuple { 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 struct IndexedTuple {}; #if VEG_HAS_NO_UNIQUE_ADDRESS #define __VEG_IMPL_LEAF(Tuple, I, ...) /* NOLINT */ \ (static_cast< \ ::proxsuite::linalg::veg::tuple::TupleLeaf const&>( \ (Tuple).inner) \ .leaf) #define __VEG_IMPL_LEAF_MUT(Tuple, I, ...) /* NOLINT */ \ (static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf&>( \ (Tuple).inner) \ .leaf) #define __VEG_IMPL_LEAF_ONCE(Tuple, I, ...) /* NOLINT */ \ (static_cast<__VA_ARGS__&&>( \ static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf&&>( \ (Tuple).inner) \ .leaf)) template 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 const&>( \ (Tuple).inner) \ .leaf_get())) #define __VEG_IMPL_LEAF_MUT(Tuple, I, ...) /* NOLINT */ \ (static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf&>( \ (Tuple).inner) \ .leaf_get()) #define __VEG_IMPL_LEAF_ONCE(Tuple, I, ...) /* NOLINT */ \ (static_cast<__VA_ARGS__&&>( \ static_cast<::proxsuite::linalg::veg::tuple::TupleLeaf&&>( \ (Tuple).inner) \ .leaf_get())) template) && !VEG_CONCEPT(final))> struct TupleLeafImpl; template struct TupleLeafImpl : T { template VEG_INLINE constexpr TupleLeafImpl(InPlace /*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(static_cast(*this)); } }; template struct TupleLeafImpl { T leaf; template VEG_INLINE constexpr TupleLeafImpl(InPlace /*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(leaf); } }; template struct TupleLeaf : TupleLeafImpl { using TupleLeafImpl::TupleLeafImpl; }; #endif namespace nb { struct unpack { VEG_TEMPLATE( (typename Fn, typename... Ts, usize... Is), requires(VEG_CONCEPT( fn_once, Ts&&...>)), VEG_INLINE constexpr auto operator(), (args, IndexedTuple, Ts...>&&), (fn, Fn)) const VEG_NOEXCEPT_IF( VEG_CONCEPT(nothrow_fn_once< Fn, proxsuite::linalg::veg::meta::invoke_result_t, Ts&&...>)) ->proxsuite::linalg::veg::meta::invoke_result_t { 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, void, Ts>))), VEG_INLINE VEG_CPP14(constexpr) void operator(), (args, IndexedTuple, Ts...>&&), (fn, Fn)) const VEG_NOEXCEPT_IF( VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once, void, Ts>))) { VEG_EVAL_ALL(fn[Fix{}](__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))), VEG_INLINE VEG_CPP14(constexpr) void operator(), (args, IndexedTuple, Ts...>&&), (fn, Fn)) const VEG_NOEXCEPT_IF(VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_mut))) { 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, proxsuite::linalg::veg::meta::invoke_result_t, Ts>, Ts>))), VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto operator(), (args, IndexedTuple, Ts...>&&), (fn, Fn)) const VEG_NOEXCEPT_IF( VEG_ALL_OF(VEG_CONCEPT( nothrow_fn_once< // inner_ith, proxsuite::linalg::veg::meta::invoke_result_t, Ts>, Ts>))) ->Tuple< proxsuite::linalg::veg::meta::invoke_result_t, Ts>...> { return { inplace[tuplify{}], _detail::WithArg, Ts>{ fn[Fix{}], __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, Ts&&>))), VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto operator(), (args, IndexedTuple, Ts...>&&), (fn, Fn)) const VEG_NOEXCEPT_IF( VEG_ALL_OF(VEG_CONCEPT( nothrow_fn_mut, Ts&&>))) ->Tuple...> { return { inplace[tuplify{}], _detail::WithArg{ fn, __VEG_IMPL_LEAF_ONCE(args, Is, Ts), }..., }; } }; } // namespace nb template struct IndexedTuple, Ts...> { struct _ : TupleLeaf... { #if !defined(VEG_WITH_CXX17_SUPPORT) #if VEG_HAS_NO_UNIQUE_ADDRESS template VEG_INLINE constexpr _(InPlace /* unused */, Fns... fns) noexcept( VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once))) : TupleLeaf{ VEG_FWD(fns)() }... { } #else template VEG_INLINE constexpr _(InPlace /*unused*/, Fns... fns) noexcept( VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once))) : TupleLeaf{ 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{ VEG_FWD(args) }..., #else #if VEG_HAS_NO_UNIQUE_ADDRESS TupleLeaf{ Ts(VEG_FWD(args)) }... #else TupleLeaf{ inplace, _detail::MoveFn{ VEG_FWD(args) } }... #endif #endif } { } VEG_TEMPLATE((typename _, typename... Fns), requires(VEG_CONCEPT(same<_, Tuplify>) && VEG_ALL_OF(VEG_CONCEPT(fn_once))), VEG_INLINE constexpr IndexedTuple, (/*tag*/, InPlace<_>), (... fns, Fns)) VEG_NOEXCEPT_IF(VEG_ALL_OF(VEG_CONCEPT(nothrow_fn_once))) : inner { #if !defined(VEG_WITH_CXX17_SUPPORT) inplace, VEG_FWD(fns)... #else #if VEG_HAS_NO_UNIQUE_ADDRESS TupleLeaf{ VEG_FWD(fns)() }... #else TupleLeaf{ inplace, VEG_FWD(fns) }... #endif #endif } { } VEG_EXPLICIT_COPY(IndexedTuple); VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto as_ref() const & VEG_NOEXCEPT->Tuple...> { return { tuplify, ref(__VEG_IMPL_LEAF(*this, Is, Ts))..., }; } VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto as_mut() VEG_NOEXCEPT->Tuple...> { return { tuplify, mut(__VEG_IMPL_LEAF_MUT(*this, Is, Ts))..., }; } template void operator[](Fix /*arg*/) const&& = delete; VEG_TEMPLATE((isize I), requires(static_cast(I) < sizeof...(Ts)), VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto operator[], (/*arg*/, Fix)) && VEG_NOEXCEPT_IF( VEG_CONCEPT(nothrow_movable(I), Ts...>>)) -> ith(I), Ts...> { return __VEG_IMPL_LEAF_ONCE( *this, static_cast(I), ith(I), Ts...>); } VEG_TEMPLATE((isize I), requires(static_cast(I) < sizeof...(Ts)), VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto operator[], (/*arg*/, Fix)) & VEG_NOEXCEPT->ith(I), Ts...>& { return __VEG_IMPL_LEAF_MUT( *this, static_cast(I), ith(I), Ts...>); } VEG_TEMPLATE((isize I), requires(static_cast(I) < sizeof...(Ts)), VEG_NODISCARD VEG_INLINE VEG_CPP14(constexpr) auto operator[], (/*arg*/, Fix)) const & VEG_NOEXCEPT->ith(I), Ts...> const& { return __VEG_IMPL_LEAF( *this, static_cast(I), ith(I), Ts...>); } }; } // namespace tuple namespace _detail { namespace meta_ { struct NonTupleBaseInfoImpl { static constexpr bool is_tuple = false; static constexpr usize size = 0; template using ith = void; using seq = void; }; template struct TupleBaseInfoImpl { static constexpr bool is_tuple = true; static constexpr usize size = sizeof...(Ts); template using ith = proxsuite::linalg::veg::ith; using seq = meta::type_sequence; using Tuple = proxsuite::linalg::veg::Tuple; using IndexedTuple = proxsuite::linalg::veg::tuple:: IndexedTuple, Ts...>; }; struct is_tuple_helper { static auto test(void*) -> NonTupleBaseInfoImpl; template static auto test(tuple::IndexedTuple, Ts...>*) -> TupleBaseInfoImpl; }; template struct IndexedToTuple; template struct IndexedToTuple, Ts...>> { using Type = Tuple; }; } // namespace meta_ } // namespace _detail namespace tuple { namespace meta { template using TupleBaseInfo = decltype(_detail::meta_::is_tuple_helper::test(static_cast(nullptr))); template using is_tuple = proxsuite::linalg::veg::meta::bool_constant::is_tuple>; template using tuple_size = proxsuite::linalg::veg::meta::constant::size>; template using tuple_element = typename TupleBaseInfo::template ith; } // namespace meta } // namespace tuple namespace concepts { namespace tuple { VEG_DEF_CONCEPT(typename T, tuple, proxsuite::linalg::veg::tuple::meta::is_tuple::value); } // namespace tuple } // namespace concepts template struct Tuple : tuple::IndexedTuple, Ts...> { using Indexed = tuple::IndexedTuple, Ts...>; using Indexed::Indexed; VEG_EXPLICIT_COPY(Tuple); }; VEG_CPP17(template Tuple(Tuplify, Ts...) -> Tuple;) namespace tuple { template VEG_NODISCARD VEG_INLINE constexpr auto get(tuple::IndexedTuple, Ts...> const& tup) VEG_NOEXCEPT->ith const& { return __VEG_IMPL_LEAF(tup, I, ith); } template VEG_NODISCARD VEG_INLINE constexpr auto get(tuple::IndexedTuple, Ts...>& tup) VEG_NOEXCEPT->ith& { return __VEG_IMPL_LEAF_MUT(tup, I, ith); } template VEG_NODISCARD VEG_INLINE constexpr auto get(tuple::IndexedTuple, Ts...> const&& tup) VEG_NOEXCEPT->ith const&& { return static_cast const&&>( __VEG_IMPL_LEAF(tup, I, ith)); } template VEG_NODISCARD VEG_INLINE constexpr auto get(tuple::IndexedTuple, Ts...>&& tup) VEG_NOEXCEPT->ith&& { return __VEG_IMPL_LEAF_ONCE(tup, I, ith); } } // namespace tuple namespace _detail { namespace _tuple { template VEG_INLINE static constexpr auto tuple_fwd(tuple::IndexedTuple, Ts...>&& tup) VEG_NOEXCEPT->Tuple { 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>))), VEG_NODISCARD VEG_INLINE constexpr auto operator(), (... args, Fns)) const VEG_NOEXCEPT_IF( VEG_ALL_OF(VEG_CONCEPT( nothrow_fn_once>))) ->proxsuite::linalg::veg::Tuple< proxsuite::linalg::veg::meta::invoke_result_t...> { return { inplace[tuplify{}], VEG_FWD(args)... }; } }; struct zip { template using PreZip = proxsuite::linalg::veg::meta::type_sequence_zip; template using Zip = proxsuite::linalg::veg::meta:: detected_t::Tuple...>; VEG_TEMPLATE( (typename... Tuples), requires(VEG_ALL_OF(VEG_CONCEPT(tuple::tuple)) && VEG_CONCEPT(all_same...>)), VEG_NODISCARD VEG_INLINE constexpr auto operator(), (... tups, Tuples)) const VEG_NOEXCEPT->Zip { return zip::apply( static_cast::IndexedTuple&&>( tups)...); } private: template VEG_INLINE static constexpr auto pre_apply( proxsuite::linalg::veg::meta::true_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT->Zip { return zip::apply(VEG_FWD(tups)...); } template VEG_INLINE static constexpr auto pre_apply( proxsuite::linalg::veg::meta::false_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT->Zip { return zip::from_ref_to_result( Tag::Type...>>{}, zip::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); } VEG_INLINE static auto apply() VEG_NOEXCEPT->Tuple<> { return {}; } template struct Helper { template using Type = Tuple...>; template VEG_INLINE constexpr auto apply(Ts&&... tups) const VEG_NOEXCEPT->Type { return { tuplify{}, VEG_FWD(first), __VEG_IMPL_LEAF_ONCE(tups, I, meta::tuple_element)..., }; } T&& first; }; template VEG_INLINE static constexpr auto apply( IndexedTuple, Ts...> first, Tuples... rest) VEG_NOEXCEPT->Tuple< // typename Helper:: // template Type...> { return { ((void)first, tuplify{}), Helper{ __VEG_IMPL_LEAF_ONCE(first, Is, Ts) } .template apply(VEG_FWD(rest)...)..., }; } template struct ConverterImpl; template struct Converter; template struct ConverterImpl, InnerTargets...> { IndexedTuple, InnerTargets&&...>&& refs; VEG_INLINE constexpr auto operator()() const && VEG_NOEXCEPT->Tuple { return { inplace[tuplify{}], _detail::MoveFn{ __VEG_IMPL_LEAF_ONCE(refs, Is, InnerTargets) }..., }; } }; template struct Converter> { using Type = ConverterImpl, InnerTargets...>; }; template VEG_INLINE static constexpr auto from_ref_to_result( Tag> /*tag*/, IndexedTuple, Tups...> zipped_refs) VEG_NOEXCEPT->Tuple { return { ((void)zipped_refs, inplace[tuplify{}]), typename Converter::Type{ __VEG_IMPL_LEAF_ONCE(zipped_refs, Is, Tups), }..., }; } }; struct cat { template using PreConcat = proxsuite::linalg::veg::meta::type_sequence_cat; template using Concat = proxsuite::linalg::veg::meta:: detected_t::Tuple...>; VEG_TEMPLATE((typename... Tuples), requires(VEG_ALL_OF(VEG_CONCEPT(tuple::tuple))), VEG_NODISCARD VEG_INLINE constexpr auto operator(), (... tups, Tuples)) const VEG_NOEXCEPT->Concat { return cat::apply( static_cast::IndexedTuple&&>( tups)...); } private: template VEG_INLINE static constexpr auto pre_apply( proxsuite::linalg::veg::meta::true_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT->Concat { return cat::apply(VEG_FWD(tups)...); } template VEG_INLINE static constexpr auto pre_apply( proxsuite::linalg::veg::meta::false_type /*unused*/, Tuples&&... tups) VEG_NOEXCEPT->Concat { return cat::template from_ref_to_result( Tag>{}, cat::apply(_detail::_tuple::tuple_fwd(VEG_FWD(tups))...)); } template VEG_INLINE static constexpr auto from_ref_to_result( Tag> /*tag*/, IndexedTuple, Refs...> refs) VEG_NOEXCEPT->proxsuite::linalg::veg::Tuple { return { inplace[tuplify{}], _detail::MoveFn{ __VEG_IMPL_LEAF_ONCE(refs, Is, Targets) }..., }; } VEG_INLINE static auto apply() VEG_NOEXCEPT->Tuple<> { return {}; } template VEG_INLINE static constexpr auto apply( IndexedTuple, Ts...>&& first, Tuples&&... rest) VEG_NOEXCEPT->proxsuite::linalg::veg::meta::type_sequence_cat< Tuple, Tuple, typename _detail::meta_::IndexedToTuple::Type...> { return cat::apply2(VEG_FWD(first), cat::apply(VEG_FWD(rest)...)); } template VEG_INLINE static constexpr auto apply2( IndexedTuple, Ts...>&& first, IndexedTuple, Us...>&& second) VEG_NOEXCEPT->Tuple { 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))), VEG_INLINE VEG_CPP14(constexpr) void operator(), (ts, IndexedTuple, RefMut...>), (us, IndexedTuple, Ref...>)) const VEG_NOEXCEPT_IF( VEG_ALL_OF(VEG_CONCEPT(nothrow_assignable))) { VEG_EVAL_ALL(__VEG_IMPL_LEAF_MUT(ts, Is, RefMut).get() = __VEG_IMPL_LEAF(us, Is, Ref).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 struct is_trivially_relocatable< tuple::IndexedTuple, Ts...>> : meta::bool_constant<(VEG_ALL_OF(is_trivially_relocatable::value))> {}; template struct is_trivially_constructible< tuple::IndexedTuple, Ts...>> : meta::bool_constant<(VEG_ALL_OF(is_trivially_constructible::value))> {}; template struct is_trivially_relocatable> : meta::bool_constant<(VEG_ALL_OF(is_trivially_relocatable::value))> {}; template struct is_trivially_constructible> : meta::bool_constant<(VEG_ALL_OF(is_trivially_constructible::value))> {}; } // namespace cpo } // namespace veg } // namespace linalg } // namespace proxsuite template struct std::tuple_size> : ::proxsuite::linalg::veg::meta::constant {}; template struct std::tuple_element> { using type = proxsuite::linalg::veg::ith; }; #include "proxsuite/linalg/veg/internal/epilogue.hpp" #endif /* end of include guard VEG_TUPLE_HPP_B8PHUNWES */