-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
877 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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))); | ||
} | ||
} | ||
|
||
|
Oops, something went wrong.