Skip to content

Commit

Permalink
introduce new seqan3::detail::transfer_type_modifier_onto (#2365)
Browse files Browse the repository at this point in the history
* [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 <[email protected]>

* 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 <[email protected]>

* Update include/seqan3/core/detail/transfer_type_modifier_onto.hpp

Co-authored-by: Enrico Seiler <[email protected]>

Co-authored-by: Jörg Winkler <[email protected]>
Co-authored-by: Enrico Seiler <[email protected]>
  • Loading branch information
3 people authored Feb 3, 2021
1 parent b9ed109 commit e7e0430
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 9 deletions.
14 changes: 5 additions & 9 deletions include/seqan3/core/configuration/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <seqan3/core/algorithm/pipeable_config_element.hpp>
#include <seqan3/core/configuration/detail/concept.hpp>
#include <seqan3/core/configuration/detail/configuration_utility.hpp>
#include <seqan3/core/detail/transfer_type_modifier_onto.hpp>
#include <seqan3/utility/tuple_utility.hpp>
#include <seqan3/utility/type_list/type_list.hpp>
#include <seqan3/utility/type_pack/traits.hpp>
Expand Down Expand Up @@ -201,15 +202,10 @@ class configuration : public std::tuple<configs_t...>

// Get the actual base tuple type from the other configuration.
using other_base_t = typename std::remove_cvref_t<other_configuration_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::is_const_v<std::remove_reference_t<other_configuration_t>>,
std::add_const_t<other_base_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::is_lvalue_reference_v<other_configuration_t>,
std::add_lvalue_reference_t<other_base_maybe_const_t>,
std::add_rvalue_reference_t<other_base_maybe_const_t>>;
using other_base_same_modifier_t = detail::transfer_type_modifier_onto_t<other_configuration_t,
other_base_t>;

// Form a new seqan3::configuration type with the concatenated configuration element types of this and the
// other configuration.
Expand All @@ -221,7 +217,7 @@ class configuration : public std::tuple<configs_t...>

// Concatenate the two configurations using their base tuple types.
return appended_configuration_t{std::tuple_cat(static_cast<base_type>(*this),
static_cast<fwd_other_base_t>(other_config))};
std::forward<other_base_same_modifier_t>(other_config))};
}
}

Expand Down
70 changes: 70 additions & 0 deletions include/seqan3/core/detail/transfer_type_modifier_onto.hpp
Original file line number Diff line number Diff line change
@@ -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 <marcel.ehrhardt AT fu-berlin.de>
* \brief Provides type traits seqan3::detail::transfer_type_modifier_onto.
*/

#pragma once

#include <seqan3/std/type_traits>

#include <seqan3/core/platform.hpp>

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 <typename source_t, typename target_t>
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::remove_reference_t<source_t>> ||
std::is_const_v<std::remove_reference_t<target_t>>,
std::add_const_t<std::remove_cvref_t<target_t>>,
std::remove_cvref_t<target_t>>;

//!\brief Transfers the `&&` type modifier to the target type.
using maybe_rvalue_reference_t = std::conditional_t<std::is_rvalue_reference_v<source_t> ||
std::is_rvalue_reference_v<target_t>,
std::add_rvalue_reference_t<maybe_const_target_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<source_t> ||
std::is_lvalue_reference_v<target_t>,
std::add_lvalue_reference_t<maybe_rvalue_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 <typename source_t, typename target_t>
using transfer_type_modifier_onto_t = typename transfer_type_modifier_onto<source_t, target_t>::type;

} // namespace seqan3::detail
1 change: 1 addition & 0 deletions test/unit/core/detail/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
142 changes: 142 additions & 0 deletions test/unit/core/detail/transfer_type_modifier_onto_test.cpp
Original file line number Diff line number Diff line change
@@ -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 <gtest/gtest.h>

#include <seqan3/core/detail/transfer_type_modifier_onto.hpp>
#include <seqan3/test/expect_same_type.hpp>

TEST(transfer_type_modifier_onto, type)
{
// target type has no modifier
EXPECT_SAME_TYPE(double, (typename seqan3::detail::transfer_type_modifier_onto<int, double>::type));
EXPECT_SAME_TYPE(double &, (typename seqan3::detail::transfer_type_modifier_onto<int &, double>::type));
EXPECT_SAME_TYPE(double &&, (typename seqan3::detail::transfer_type_modifier_onto<int &&, double>::type));
EXPECT_SAME_TYPE(double const, (typename seqan3::detail::transfer_type_modifier_onto<int const, double>::type));
EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto<int const &, double>::type));
EXPECT_SAME_TYPE(double const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double>::type));

// target type has lvalue reference modifier
EXPECT_SAME_TYPE(double &, (typename seqan3::detail::transfer_type_modifier_onto<int, double &>::type));
EXPECT_SAME_TYPE(double & /*&*/, (typename seqan3::detail::transfer_type_modifier_onto<int &, double &>::type));
EXPECT_SAME_TYPE(double & /*&&*/, (typename seqan3::detail::transfer_type_modifier_onto<int &&, double &>::type));
EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto<int const, double &>::type));
EXPECT_SAME_TYPE(double const & /*&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int const &, double &>::type));
EXPECT_SAME_TYPE(double const & /*&&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double &>::type));

// target type has rvalue reference modifier
EXPECT_SAME_TYPE(double &&, (typename seqan3::detail::transfer_type_modifier_onto<int, double &&>::type));
EXPECT_SAME_TYPE(double /*&&*/ &, (typename seqan3::detail::transfer_type_modifier_onto<int &, double &&>::type));
EXPECT_SAME_TYPE(double && /*&&*/, (typename seqan3::detail::transfer_type_modifier_onto<int &&, double &&>::type));
EXPECT_SAME_TYPE(double const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const, double &&>::type));
EXPECT_SAME_TYPE(double const /*&&*/ &,
(typename seqan3::detail::transfer_type_modifier_onto<int const &, double &&>::type));
EXPECT_SAME_TYPE(double const /*&&*/ &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double &&>::type));

// target type has const modifier
EXPECT_SAME_TYPE(double const, (typename seqan3::detail::transfer_type_modifier_onto<int, double const>::type));
EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto<int &, double const>::type));
EXPECT_SAME_TYPE(double const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int &&, double const>::type));
EXPECT_SAME_TYPE(double /*const*/ const,
(typename seqan3::detail::transfer_type_modifier_onto<int const, double const>::type));
EXPECT_SAME_TYPE(double /*const*/ const &,
(typename seqan3::detail::transfer_type_modifier_onto<int const &, double const>::type));
EXPECT_SAME_TYPE(double /*const*/ const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double const>::type));

// target type has const lvalue reference modifier
EXPECT_SAME_TYPE(double const &, (typename seqan3::detail::transfer_type_modifier_onto<int, double const &>::type));
EXPECT_SAME_TYPE(double const & /*&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int &, double const &>::type));
EXPECT_SAME_TYPE(double const & /*&&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int &&, double const &>::type));
EXPECT_SAME_TYPE(double /*const*/ const &,
(typename seqan3::detail::transfer_type_modifier_onto<int const, double const &>::type));
EXPECT_SAME_TYPE(double /*const*/ const & /*&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int const &, double const &>::type));
EXPECT_SAME_TYPE(double /*const*/ const & /*&&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double const &>::type));

// target type has const rvalue reference modifier
EXPECT_SAME_TYPE(double const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int, double const &&>::type));
EXPECT_SAME_TYPE(double const /*&&*/ &,
(typename seqan3::detail::transfer_type_modifier_onto<int &, double const &&>::type));
EXPECT_SAME_TYPE(double const && /*&&*/,
(typename seqan3::detail::transfer_type_modifier_onto<int &&, double const &&>::type));
EXPECT_SAME_TYPE(double /*const*/ const &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const, double const &&>::type));
EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &,
(typename seqan3::detail::transfer_type_modifier_onto<int const &, double const &&>::type));
EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &&,
(typename seqan3::detail::transfer_type_modifier_onto<int const &&, double const &&>::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<int, double>));
EXPECT_SAME_TYPE(double &, (seqan3::detail::transfer_type_modifier_onto_t<int &, double>));
EXPECT_SAME_TYPE(double &&, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double>));
EXPECT_SAME_TYPE(double const, (seqan3::detail::transfer_type_modifier_onto_t<int const, double>));
EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t<int const &, double>));
EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t<int const &&, double>));

// target type has lvalue reference modifier
EXPECT_SAME_TYPE(double &, (seqan3::detail::transfer_type_modifier_onto_t<int, double &>));
EXPECT_SAME_TYPE(double & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &, double &>));
EXPECT_SAME_TYPE(double & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double &>));
EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t<int const, double &>));
EXPECT_SAME_TYPE(double const & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t<int const &, double &>));
EXPECT_SAME_TYPE(double const & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t<int const &&, double &>));

// target type has rvalue reference modifier
EXPECT_SAME_TYPE(double &&, (seqan3::detail::transfer_type_modifier_onto_t<int, double &&>));
EXPECT_SAME_TYPE(double /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t<int &, double &&>));
EXPECT_SAME_TYPE(double && /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double &&>));
EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t<int const, double &&>));
EXPECT_SAME_TYPE(double const /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t<int const &, double &&>));
EXPECT_SAME_TYPE(double const /*&&*/ &&, (seqan3::detail::transfer_type_modifier_onto_t<int const &&, double &&>));

// target type has const modifier
EXPECT_SAME_TYPE(double const, (seqan3::detail::transfer_type_modifier_onto_t<int, double const>));
EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t<int &, double const>));
EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double const>));
EXPECT_SAME_TYPE(double /*const*/ const, (seqan3::detail::transfer_type_modifier_onto_t<int const, double const>));
EXPECT_SAME_TYPE(double /*const*/ const &,
(seqan3::detail::transfer_type_modifier_onto_t<int const &, double const>));
EXPECT_SAME_TYPE(double /*const*/ const &&,
(seqan3::detail::transfer_type_modifier_onto_t<int const &&, double const>));

// target type has const lvalue reference modifier
EXPECT_SAME_TYPE(double const &, (seqan3::detail::transfer_type_modifier_onto_t<int, double const &>));
EXPECT_SAME_TYPE(double const & /*&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &, double const &>));
EXPECT_SAME_TYPE(double const & /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double const &>));
EXPECT_SAME_TYPE(double /*const*/ const &,
(seqan3::detail::transfer_type_modifier_onto_t<int const, double const &>));
EXPECT_SAME_TYPE(double /*const*/ const & /*&*/,
(seqan3::detail::transfer_type_modifier_onto_t<int const &, double const &>));
EXPECT_SAME_TYPE(double /*const*/ const & /*&&*/,
(seqan3::detail::transfer_type_modifier_onto_t<int const &&, double const &>));

// target type has const rvalue reference modifier
EXPECT_SAME_TYPE(double const &&, (seqan3::detail::transfer_type_modifier_onto_t<int, double const &&>));
EXPECT_SAME_TYPE(double const /*&&*/ &, (seqan3::detail::transfer_type_modifier_onto_t<int &, double const &&>));
EXPECT_SAME_TYPE(double const && /*&&*/, (seqan3::detail::transfer_type_modifier_onto_t<int &&, double const &&>));
EXPECT_SAME_TYPE(double /*const*/ const &&,
(seqan3::detail::transfer_type_modifier_onto_t<int const, double const &&>));
EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &,
(seqan3::detail::transfer_type_modifier_onto_t<int const &, double const &&>));
EXPECT_SAME_TYPE(double /*const*/ const /*&&*/ &&,
(seqan3::detail::transfer_type_modifier_onto_t<int const &&, double const &&>));
}

0 comments on commit e7e0430

Please sign in to comment.