Skip to content

Commit

Permalink
[WIP] views::zip
Browse files Browse the repository at this point in the history
  • Loading branch information
eseiler committed May 2, 2022
1 parent 3440dd6 commit f46b065
Show file tree
Hide file tree
Showing 4 changed files with 877 additions and 24 deletions.
4 changes: 2 additions & 2 deletions include/seqan3/alignment/matrix/detail/affine_cell_proxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class affine_cell_proxy : public tuple_t
//!\brief Converting move-constructor.
template <typename other_tuple_t>
//!\cond
requires std::constructible_from<tuple_t, other_tuple_t>
requires std::constructible_from<tuple_t, other_tuple_t &&>
//!\endcond
explicit affine_cell_proxy(affine_cell_proxy<other_tuple_t> && other) :
tuple_t{static_cast<other_tuple_t &&>(std::move(other))}
Expand Down Expand Up @@ -194,7 +194,7 @@ class affine_cell_proxy : public tuple_t
//!\brief Converting move-assignment.
template <typename other_tuple_t>
//!\cond
requires std::assignable_from<tuple_t &, other_tuple_t>
// requires std::assignable_from<tuple_t &, other_tuple_t &&> Needs some std::pair/tuple magic
//!\endcond
affine_cell_proxy & operator=(affine_cell_proxy<other_tuple_t> && other)
{
Expand Down
325 changes: 325 additions & 0 deletions include/seqan3/utility/views/common_tuple.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
#pragma once

#include <seqan3/utility/tuple/concept.hpp>

namespace seqan3::detail
{

template <class... Types>
class common_tuple : public std::tuple<Types...>
{
private:
using tuple_t = std::tuple<Types...>;

template <typename fun_t, typename tuple_t>
constexpr static auto tuple_transform(fun_t && f, tuple_t && tuple)
{
return std::apply([&] <typename... ts> (ts && ... elements)
{
return common_tuple<std::invoke_result_t<fun_t &, ts>...>
{
std::invoke(f, std::forward<ts>(elements))...
};
},
std::forward<tuple_t>(tuple));
}

public:
using tuple_t::tuple_t;
using tuple_t::operator=;

common_tuple() = default; //!< Defaulted.
common_tuple(common_tuple const &) = default; //!< Defaulted.
common_tuple(common_tuple &&) = default; //!< Defaulted.
~common_tuple() = default; //!< Defaulted.


/*!\name cpp23 constructors
* \{
*/
template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes)) && (std::is_constructible_v<Types, UTypes&> && ...)
constexpr common_tuple(common_tuple<UTypes...> & other) : common_tuple(tuple_transform([] (auto & i) -> decltype(auto) { return i; }, other))
{}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes)) && (std::is_constructible_v<Types, UTypes const> && ...)
constexpr common_tuple(common_tuple<UTypes...> const && other) : common_tuple(tuple_transform([] <typename I> (I && i) { return std::forward<I>(i); }, other))
{}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes)) && (std::is_constructible_v<Types, UTypes&> && ...)
explicit constexpr common_tuple(std::tuple<UTypes...> & other) : common_tuple(tuple_transform([] (auto & i) -> decltype(auto) { return i; }, other))
{}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes)) && (std::is_constructible_v<Types, UTypes const> && ...)
explicit constexpr common_tuple(std::tuple<UTypes...> const && other) : common_tuple(tuple_transform([] <typename I> (I && i) { return std::forward<I>(i); }, other))
{}
//!\}

/*!\name cpp23 assignment operators
* \{
*/
constexpr common_tuple& operator=(const common_tuple& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr const common_tuple& operator=(const common_tuple& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr common_tuple& operator=(common_tuple&& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<Types>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr const common_tuple& operator=(common_tuple&& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<Types>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr common_tuple& operator=(const common_tuple<UTypes...>& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr const common_tuple& operator=(const common_tuple<UTypes...>& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr common_tuple& operator=(common_tuple<UTypes...>&& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<UTypes>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr const common_tuple& operator=(common_tuple<UTypes...>&& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<UTypes>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr common_tuple& operator=(const std::tuple<Types...>& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr const common_tuple& operator=(const std::tuple<Types...>& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr common_tuple& operator=(std::tuple<Types...>&& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<Types>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

constexpr const common_tuple& operator=(std::tuple<Types...>&& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<Types>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr common_tuple& operator=(const std::tuple<UTypes...>& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr const common_tuple& operator=(const std::tuple<UTypes...>& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::get<N>(other)), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr common_tuple& operator=(std::tuple<UTypes...>&& other)
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<UTypes>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}

template <class... UTypes>
requires (sizeof...(Types) == sizeof...(UTypes))
constexpr const common_tuple& operator=(std::tuple<UTypes...>&& other) const
{
[&] <size_t... N> (std::integer_sequence<size_t, N...>)
{
((std::get<N>(*this) = std::forward<UTypes>(std::get<N>(other))), ...);
} (std::index_sequence_for<Types...>{});

return *this;
}
//!\}
};
}


namespace std
{
template <typename... args>
struct tuple_size<seqan3::detail::common_tuple<args...>> : public tuple_size<tuple<args...>>
{};

template <size_t index, typename... args>
struct tuple_element<index, seqan3::detail::common_tuple<args...>> : public tuple_element<index, tuple<args...>>
{};

template <class... Ts, class... Us>
requires requires { typename seqan3::detail::common_tuple<std::common_type_t<Ts, Us>...>; }
struct common_type<seqan3::detail::common_tuple<Ts...>, seqan3::detail::common_tuple<Us...>>
{
using type = seqan3::detail::common_tuple<std::common_type_t<Ts, Us>...>;
};

template <class... Ts, class... Us, template <class> class TQual, template <class> class UQual>
requires requires { typename seqan3::detail::common_tuple<std::common_reference_t<TQual<Ts>, UQual<Us>>...>; }
struct basic_common_reference<seqan3::detail::common_tuple<Ts...>, seqan3::detail::common_tuple<Us...>, TQual, UQual>
{
using type = seqan3::detail::common_tuple<std::common_reference_t<TQual<Ts>, UQual<Us>>...>;
};

template <std::size_t i, typename ...types>
constexpr std::tuple_element_t<i, seqan3::detail::common_tuple<types...>> & get(seqan3::detail::common_tuple<types...> & t) noexcept
requires (i < sizeof...(types))
{
return std::get<i>(static_cast<std::tuple<types...> &>(t));
}

template <std::size_t i, typename ...types>
constexpr std::tuple_element_t<i, seqan3::detail::common_tuple<types...>> const & get(seqan3::detail::common_tuple<types...> const & t) noexcept
requires (i < sizeof...(types))
{
return std::get<i>(static_cast<std::tuple<types...> const &>(t));
}

template <std::size_t i, typename ...types>
constexpr std::tuple_element_t<i, seqan3::detail::common_tuple<types...>> && get(seqan3::detail::common_tuple<types...> && t) noexcept
requires (i < sizeof...(types))
{
return std::get<i>(static_cast<std::tuple<types...> &&>(std::move(t)));
}

template <std::size_t i, typename ...types>
constexpr std::tuple_element_t<i, seqan3::detail::common_tuple<types...>> const && get(seqan3::detail::common_tuple<types...> const && t) noexcept
requires (i < sizeof...(types))
{
return std::get<i>(static_cast<std::tuple<types...> const &&>(std::move(t)));
}

template <typename type, typename ...types>
constexpr type & get(seqan3::detail::common_tuple<types...> & t) noexcept
requires (seqan3::pack_traits::count<type, types...> == 1)
{
return std::get<type>(static_cast<std::tuple<types...> &>(t));
}

template <typename type, typename ...types>
constexpr type const & get(seqan3::detail::common_tuple<types...> const & t) noexcept
requires (seqan3::pack_traits::count<type, types...> == 1)
{
return std::get<type>(static_cast<std::tuple<types...> const &>(t));
}

template <typename type, typename ...types>
constexpr type && get(seqan3::detail::common_tuple<types...> && t) noexcept
requires (seqan3::pack_traits::count<type, types...> == 1)
{
return std::get<type>(static_cast<std::tuple<types...> &&>(std::move(t)));
}

template <typename type, typename ...types>
constexpr type const && get(seqan3::detail::common_tuple<types...> const && t) noexcept
requires (seqan3::pack_traits::count<type, types...> == 1)
{
return std::get<type>(static_cast<std::tuple<types...> const &&>(std::move(t)));
}
}


Loading

0 comments on commit f46b065

Please sign in to comment.