From e7e04307402a6a3ffcf7bb9807eeb69723c02d1d Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 3 Feb 2021 14:24:00 +0100 Subject: [PATCH] introduce new seqan3::detail::transfer_type_modifier_onto (#2365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FEATURE] introduce new seqan3::detail::transfer_type_modifier_onto * [FEATURE] use new seqan3::detail::transfer_type_modifier_onto * Update include/seqan3/core/detail/transfer_type_modifier_onto.hpp Co-authored-by: Jörg Winkler * Update include/seqan3/core/detail/transfer_type_modifier_onto.hpp * Update include/seqan3/core/detail/transfer_type_modifier_onto.hpp Co-authored-by: Enrico Seiler * Update include/seqan3/core/detail/transfer_type_modifier_onto.hpp Co-authored-by: Enrico Seiler Co-authored-by: Jörg Winkler Co-authored-by: Enrico Seiler --- .../core/configuration/configuration.hpp | 14 +- .../detail/transfer_type_modifier_onto.hpp | 70 +++++++++ test/unit/core/detail/CMakeLists.txt | 1 + .../transfer_type_modifier_onto_test.cpp | 142 ++++++++++++++++++ 4 files changed, 218 insertions(+), 9 deletions(-) create mode 100644 include/seqan3/core/detail/transfer_type_modifier_onto.hpp create mode 100644 test/unit/core/detail/transfer_type_modifier_onto_test.cpp diff --git a/include/seqan3/core/configuration/configuration.hpp b/include/seqan3/core/configuration/configuration.hpp index 2e16ad2d43..64d90f2070 100644 --- a/include/seqan3/core/configuration/configuration.hpp +++ b/include/seqan3/core/configuration/configuration.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -201,15 +202,10 @@ class configuration : public std::tuple // Get the actual base tuple type from the other configuration. using other_base_t = typename std::remove_cvref_t::base_type; - // The other base tuple type matching the const qualifier of the input parameter. - using other_base_maybe_const_t = - std::conditional_t>, - std::add_const_t, - other_base_t>; + // The other base tuple type matching the reference type and the const qualifier of the input parameter. - using fwd_other_base_t = std::conditional_t, - std::add_lvalue_reference_t, - std::add_rvalue_reference_t>; + using other_base_same_modifier_t = detail::transfer_type_modifier_onto_t; // Form a new seqan3::configuration type with the concatenated configuration element types of this and the // other configuration. @@ -221,7 +217,7 @@ class configuration : public std::tuple // Concatenate the two configurations using their base tuple types. return appended_configuration_t{std::tuple_cat(static_cast(*this), - static_cast(other_config))}; + std::forward(other_config))}; } } diff --git a/include/seqan3/core/detail/transfer_type_modifier_onto.hpp b/include/seqan3/core/detail/transfer_type_modifier_onto.hpp new file mode 100644 index 0000000000..4f394ec471 --- /dev/null +++ b/include/seqan3/core/detail/transfer_type_modifier_onto.hpp @@ -0,0 +1,70 @@ +// ----------------------------------------------------------------------------------------------------- +// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin +// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik +// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License +// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md +// ----------------------------------------------------------------------------------------------------- + +/*!\file + * \author Marcel Ehrhardt + * \brief Provides type traits seqan3::detail::transfer_type_modifier_onto. + */ + +#pragma once + +#include + +#include + +namespace seqan3::detail +{ + +/*!\brief Transfers the type modifier `&`, `&&` and `const` (and any combination) to the target type. + * \implements seqan3::transformation_trait + * \tparam source_t The type you wish to transfer the type modifier from. + * \tparam target_t The type you wish to transfer the type modifier to. + * \ingroup core + * If the `target_t` already has a type modifier, e.g. `const`, it will keep that type modifier. + * + * If the resulting type would have the type modifier `&&` and `&` at the same time, it follows the rule of reference + * collapsing, that means `&` will be preferred. + * \sa https://en.cppreference.com/w/cpp/language/reference#Reference_collapsing + */ +template +struct transfer_type_modifier_onto +{ +private: + //!\brief Transfers the `const` type modifier to the target type. + using maybe_const_target_t = std::conditional_t> || + std::is_const_v>, + std::add_const_t>, + std::remove_cvref_t>; + + //!\brief Transfers the `&&` type modifier to the target type. + using maybe_rvalue_reference_t = std::conditional_t || + std::is_rvalue_reference_v, + std::add_rvalue_reference_t, + maybe_const_target_t>; + + //!\brief Transfers the `&` type modifier to the target type. + using maybe_lvalue_reference_target_t = std::conditional_t || + std::is_lvalue_reference_v, + std::add_lvalue_reference_t, + maybe_rvalue_reference_t>; +public: + + //!\brief Transfers the type modifier `&`, `&&` and `const` (and any combination) to the target type. + using type = maybe_lvalue_reference_target_t; +}; + +/*!\brief Transfers the type modifier `&`, `&&` and `const` (and any combination) to the target type + * (transformation_trait shortcut). + * \tparam source_t The type you wish to transfer the type modifier from. + * \tparam target_t The type you wish to transfer the type modifier to. + * \see seqan3::detail::transfer_type_modifier_onto + * \relates seqan3::detail::transfer_type_modifier_onto + */ +template +using transfer_type_modifier_onto_t = typename transfer_type_modifier_onto::type; + +} // namespace seqan3::detail diff --git a/test/unit/core/detail/CMakeLists.txt b/test/unit/core/detail/CMakeLists.txt index 9bb3f9e258..076c3f52c8 100644 --- a/test/unit/core/detail/CMakeLists.txt +++ b/test/unit/core/detail/CMakeLists.txt @@ -6,4 +6,5 @@ seqan3_test(pack_algorithm_test.cpp) seqan3_test(strong_type_debug_stream_test.cpp) seqan3_test(strong_type_test.cpp) seqan3_test(template_inspection_test.cpp) +seqan3_test(transfer_type_modifier_onto_test.cpp) seqan3_test(type_name_as_string_test.cpp) diff --git a/test/unit/core/detail/transfer_type_modifier_onto_test.cpp b/test/unit/core/detail/transfer_type_modifier_onto_test.cpp new file mode 100644 index 0000000000..f9fb77adf8 --- /dev/null +++ b/test/unit/core/detail/transfer_type_modifier_onto_test.cpp @@ -0,0 +1,142 @@ +// ----------------------------------------------------------------------------------------------------- +// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin +// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik +// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License +// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md +// ----------------------------------------------------------------------------------------------------- + +#include + +#include +#include + +TEST(transfer_type_modifier_onto, type) +{ + // target type has no modifier + EXPECT_SAME_TYPE(double, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double &&, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + + // target type has lvalue reference modifier + EXPECT_SAME_TYPE(double &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double & /*&*/, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double & /*&&*/, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const & /*&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const & /*&&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + + // target type has rvalue reference modifier + EXPECT_SAME_TYPE(double &&, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*&&*/ &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double && /*&&*/, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const /*&&*/ &, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const /*&&*/ &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + + // target type has const modifier + EXPECT_SAME_TYPE(double const, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const &, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + + // target type has const lvalue reference modifier + EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const & /*&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const & /*&&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const &, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const & /*&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const & /*&&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + + // target type has const rvalue reference modifier + EXPECT_SAME_TYPE(double const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const /*&&*/ &, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double const && /*&&*/, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &, + (typename seqan3::detail::transfer_type_modifier_onto::type)); + EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &&, + (typename seqan3::detail::transfer_type_modifier_onto::type)); +} + +TEST(transfer_type_modifier_onto, type_t_helper) +{ + // target type has no modifier + EXPECT_SAME_TYPE(double, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double &&, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t)); + + // target type has lvalue reference modifier + EXPECT_SAME_TYPE(double &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + + // target type has rvalue reference modifier + EXPECT_SAME_TYPE(double &&, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double && /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const /*&&*/ &&, (seqan3::detail::transfer_type_modifier_onto_t)); + + // target type has const modifier + EXPECT_SAME_TYPE(double const, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const &, + (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const &&, + (seqan3::detail::transfer_type_modifier_onto_t)); + + // target type has const lvalue reference modifier + EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const &, + (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const & /*&*/, + (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const & /*&&*/, + (seqan3::detail::transfer_type_modifier_onto_t)); + + // target type has const rvalue reference modifier + EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double const && /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const &&, + (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &, + (seqan3::detail::transfer_type_modifier_onto_t)); + EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &&, + (seqan3::detail::transfer_type_modifier_onto_t)); +}