Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap meaning of is_alternative and holds_alternative #2596

Merged
merged 4 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ regression test suite and patches at https://github.com/seqan/seqan3/tree/master
`using namespace seqan3::literals` to import literal operators. The old way of explicitly importing specific
operators via `using seqan3::operator""_{dna4, rna4, ...}` is not affected by this change
([\#2568](https://github.com/seqan/seqan3/pull/2568)).
* **Breaking change**: Swapped the meaning of `seqan3::alphabet_variant::is_alternative` and
`seqan3::alphabet_variant::holds_alternative` ([\#2596](https://github.com/seqan/seqan3/pull/2596)).

#### Argument Parser

Expand Down
79 changes: 56 additions & 23 deletions include/seqan3/alphabet/composite/alphabet_variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ namespace seqan3
* assign to that type first and then assign to the variant, e.g.
*
* \include test/snippet/alphabet/composite/alphabet_variant_char_representation.cpp
*
* \stableapi{Since version 3.1.}
*/
template <typename ...alternative_types>
//!\cond
Expand Down Expand Up @@ -150,11 +152,17 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
using base_t::to_rank;
using base_t::assign_rank;

//!\brief Expose the alternative types to concept checks in metaprogramming.
//!\private
/*!\brief Expose the alternative types to concept checks in metaprogramming.
* \private
* \details
* \noapi
*/
using seqan3_required_types = type_list<alternative_types...>;
//!\brief Expose the recursive alternative types to concept checks in metaprogramming.
//!\private
/*!\brief Expose the recursive alternative types to concept checks in metaprogramming.
* \private
* \details
* \noapi
*/
using seqan3_recursive_required_types =
list_traits::concat<seqan3_required_types,
detail::transformation_trait_or_t<detail::recursive_required_types<alternative_types>,
Expand All @@ -163,10 +171,12 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
/*!\brief Returns true if alternative_t is one of the given alternative types.
* \tparam alternative_t The type to check.
*
* \include test/snippet/alphabet/composite/alphabet_variant_holds_alternative.cpp
* \include test/snippet/alphabet/composite/alphabet_variant_is_alternative.cpp
*
* \stableapi{Since version 3.1.}
*/
template <typename alternative_t>
static constexpr bool holds_alternative() noexcept
static constexpr bool is_alternative() noexcept
{
return seqan3::pack_traits::contains<alternative_t, alternative_types...>;
}
Expand All @@ -186,14 +196,16 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
* \param alternative The value of a alternative that should be assigned.
*
* \include test/snippet/alphabet/composite/alphabet_variant_value_construction.cpp
*
* \stableapi{Since version 3.1.}
*/
template <typename alternative_t>
//!\cond
requires (!std::same_as<alternative_t, alphabet_variant>) &&
(!std::is_base_of_v<alphabet_variant, alternative_t>) &&
(!list_traits::contains<alphabet_variant,
detail::transformation_trait_or_t<detail::recursive_required_types<alternative_t>, type_list<>>>) &&
(holds_alternative<alternative_t>())
(is_alternative<alternative_t>())
//!\endcond
constexpr alphabet_variant(alternative_t const alternative) noexcept
{
Expand All @@ -215,6 +227,8 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
* * seqan3::dna4 and seqan3::rna4 are implicitly convertible to each other so the variant accepts either.
* * Construction via `{}` considers implicit and explicit conversions.
* * Construction via `=` considers only implicit conversions (but that is sufficient here).
*
* \experimentalapi{Experimental since version 3.1.}
*/
template <typename indirect_alternative_t>
//!\cond
Expand Down Expand Up @@ -270,7 +284,10 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
*
* \details
*
* Most assignments happen through implicit conversion and the default assignment operator. This constructor is for the rest.
* Most assignments happen through implicit conversion and the default assignment operator. This assignment operator
* is for the rest.
*
* \experimentalapi{Experimental since version 3.1.}
*/
template <typename indirect_alternative_t>
//!\cond
Expand All @@ -293,27 +310,35 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
/*!\name Conversion (by index)
* \{
*/
//!\brief Whether the variant alphabet currently holds a value of the given alternative.
//!\tparam index Index of the alternative to check for.
/*!\brief Whether the variant alphabet currently holds a value of the given alternative.
* \tparam index Index of the alternative to check for.
* \sa std::variant::holds_alternative
* \details
* \experimentalapi{Experimental since version 3.1.}
*/
template <size_t index>
constexpr bool is_alternative() const noexcept
constexpr bool holds_alternative() const noexcept
{
static_assert(index < alphabet_size, "The alphabet_variant contains less alternatives than you are checking.");
return (to_rank() >= partial_sum_sizes[index]) && (to_rank() < partial_sum_sizes[index + 1]);
}

/*!\brief Convert to the specified alphabet (throws if is_alternative() would be false).
/*!\brief Convert to the specified alphabet (throws if holds_alternative() would be false).
* \tparam index Index of the alternative to check for.
* \throws std::bad_variant_access If the variant_alphabet currently holds the value of a different alternative.
* \details
* \experimentalapi{Experimental since version 3.1.}
*/
template <size_t index>
constexpr auto convert_to() const
{
return convert_impl<index, true>();
}

/*!\brief Convert to the specified alphabet (**undefined behaviour** if is_alternative() would be false).
/*!\brief Convert to the specified alphabet (**undefined behaviour** if holds_alternative() would be false).
* \tparam index Index of the alternative to check for.
* \details
* \experimentalapi{Experimental since version 3.1.}
*/
template <size_t index>
constexpr auto convert_unsafely_to() const noexcept
Expand All @@ -325,27 +350,31 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
/*!\name Conversion (by type)
* \{
*/
/*!\copybrief is_alternative()
/*!\copybrief holds_alternative()
* \tparam alternative_t The type of the alternative that you wish to check for.
* \details
* \stableapi{Since version 3.1.}
*/
template <typename alternative_t>
constexpr bool is_alternative() const noexcept
constexpr bool holds_alternative() const noexcept
//!\cond
requires (holds_alternative<alternative_t>())
requires (is_alternative<alternative_t>())
//!\endcond
{
constexpr size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
return is_alternative<index>();
return holds_alternative<index>();
}

/*!\copybrief convert_to()
* \tparam alternative_t The type of the alternative that you wish to check for.
* \throws std::bad_variant_access If the variant_alphabet currently holds the value of a different alternative.
* \details
* \experimentalapi{Experimental since version 3.1.}
*/
template <typename alternative_t>
constexpr alternative_t convert_to() const
//!\cond
requires (holds_alternative<alternative_t>())
requires (is_alternative<alternative_t>())
//!\endcond
{
constexpr size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
Expand All @@ -354,11 +383,13 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types

/*!\copybrief convert_unsafely_to()
* \tparam alternative_t The type of the alternative that you wish to check for.
* \details
* \experimentalapi{Experimental since version 3.1.}
*/
template <typename alternative_t>
constexpr alternative_t convert_unsafely_to() const noexcept
//!\cond
requires (holds_alternative<alternative_t>())
requires (is_alternative<alternative_t>())
//!\endcond
{
constexpr size_t index = seqan3::list_traits::find<alternative_t, alternatives>;
Expand All @@ -385,6 +416,8 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
* To determine (in-)equality, it is first deduced which alternative the argument is comparable with.
* It is then checked if the variant currently is in that alternative's state and if yes whether the values compare
* to `true`; else `false` is returned.
* \details
* \stableapi{Since version 3.1.}
*/
template <typename alphabet_variant_t, typename indirect_alternative_type>
friend constexpr auto operator==(alphabet_variant_t const lhs, indirect_alternative_type const rhs) noexcept
Expand All @@ -398,7 +431,7 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
constexpr auto alternative_position = seqan3::list_traits::find_if<alternative_predicate::template invoke,
alternatives>;
using alternative_t = seqan3::list_traits::at<alternative_position, alternatives>;
return lhs.template is_alternative<alternative_t>() && (lhs.template convert_unsafely_to<alternative_t>() == rhs);
return lhs.template holds_alternative<alternative_t>() && (lhs.template convert_unsafely_to<alternative_t>() == rhs);
}

//!\copydoc operator==(alphabet_variant_t const lhs, indirect_alternative_type const rhs)
Expand Down Expand Up @@ -460,7 +493,7 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types

if constexpr (throws)
{
if (!is_alternative<index>()) // [[unlikely]]
if (!holds_alternative<index>()) // [[unlikely]]
{
throw std::bad_variant_access{};
}
Expand Down Expand Up @@ -523,7 +556,7 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
//!\param alternative The value of a alternative.
template <size_t index, typename alternative_t>
//!\cond
requires (holds_alternative<alternative_t>())
requires (is_alternative<alternative_t>())
//!\endcond
static constexpr rank_type rank_by_index_(alternative_t const & alternative) noexcept
{
Expand All @@ -536,7 +569,7 @@ class alphabet_variant : public alphabet_base<alphabet_variant<alternative_types
//!\param alternative The value of a alternative.
template <typename alternative_t>
//!\cond
requires (holds_alternative<alternative_t>())
requires (is_alternative<alternative_t>())
//!\endcond
static constexpr rank_type rank_by_type_(alternative_t const & alternative) noexcept
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
From 4c511eaa512621d785d268d625c786a9495b76f0 Mon Sep 17 00:00:00 2001
From: Enrico Seiler <enrico.seiler@hotmail.de>
Date: Tue, 4 May 2021 15:12:59 +0200
Subject: [PATCH 26/26] [API] [BREAKAGE] [MISC] Swap is_alternative and
holds_alternative (#2596)

---
.../composite/alphabet_variant_holds_alternative.cpp | 6 +++---
.../alphabet/composite/alphabet_variant_test.cpp | 12 ++++++------
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/test/snippet/alphabet/composite/alphabet_variant_holds_alternative.cpp b/test/snippet/alphabet/composite/alphabet_variant_holds_alternative.cpp
index 34aaf1b59..200ad0f89 100644
--- a/test/snippet/alphabet/composite/alphabet_variant_holds_alternative.cpp
+++ b/test/snippet/alphabet/composite/alphabet_variant_holds_alternative.cpp
@@ -7,7 +7,7 @@ int main()
{
using variant_t = seqan3::alphabet_variant<seqan3::dna5, seqan3::gap>;

- static_assert(variant_t::holds_alternative<seqan3::dna5>(), "dna5 is an alternative of variant_t");
- static_assert(!variant_t::holds_alternative<seqan3::dna4>(), "dna4 is not an alternative of variant_t");
- static_assert(variant_t::holds_alternative<seqan3::gap>(), "gap is an alternative of variant_t");
+ static_assert(variant_t::is_alternative<seqan3::dna5>(), "dna5 is an alternative of variant_t");
+ static_assert(!variant_t::is_alternative<seqan3::dna4>(), "dna4 is not an alternative of variant_t");
+ static_assert(variant_t::is_alternative<seqan3::gap>(), "gap is an alternative of variant_t");
}
diff --git a/test/unit/alphabet/composite/alphabet_variant_test.cpp b/test/unit/alphabet/composite/alphabet_variant_test.cpp
index acbe102d7..e2ac36e1b 100644
--- a/test/unit/alphabet/composite/alphabet_variant_test.cpp
+++ b/test/unit/alphabet/composite/alphabet_variant_test.cpp
@@ -280,9 +280,9 @@ TEST(alphabet_variant_test, convert_by_index)
seqan3::alphabet_variant<seqan3::dna4, seqan3::dna5, seqan3::gap> u;
u = 'C'_dna5;

- EXPECT_FALSE(u.is_alternative<0>());
- EXPECT_TRUE(u.is_alternative<1>());
- EXPECT_FALSE(u.is_alternative<2>());
+ EXPECT_FALSE(u.holds_alternative<0>());
+ EXPECT_TRUE(u.holds_alternative<1>());
+ EXPECT_FALSE(u.holds_alternative<2>());

EXPECT_THROW(u.convert_to<0>(), std::bad_variant_access);
EXPECT_NO_THROW(u.convert_to<1>());
@@ -302,9 +302,9 @@ TEST(alphabet_variant_test, convert_by_type)
seqan3::alphabet_variant<seqan3::dna4, seqan3::dna5, seqan3::gap> u;
u = 'C'_dna5;

- EXPECT_FALSE(u.is_alternative<seqan3::dna4>());
- EXPECT_TRUE(u.is_alternative<seqan3::dna5>());
- EXPECT_FALSE(u.is_alternative<seqan3::gap>());
+ EXPECT_FALSE(u.holds_alternative<seqan3::dna4>());
+ EXPECT_TRUE(u.holds_alternative<seqan3::dna5>());
+ EXPECT_FALSE(u.holds_alternative<seqan3::gap>());

EXPECT_THROW(u.convert_to<seqan3::dna4>(), std::bad_variant_access);
EXPECT_NO_THROW(u.convert_to<seqan3::dna5>());
--
2.25.1

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <seqan3/alphabet/composite/alphabet_variant.hpp>
#include <seqan3/alphabet/gap/gap.hpp>
#include <seqan3/alphabet/nucleotide/all.hpp>
#include <gtest/gtest.h>

int main()
{
using variant_t = seqan3::alphabet_variant<seqan3::dna5, seqan3::gap>;

static_assert(variant_t::is_alternative<seqan3::dna5>(), "dna5 is an alternative of variant_t");
static_assert(!variant_t::is_alternative<seqan3::dna4>(), "dna4 is not an alternative of variant_t");
static_assert(variant_t::is_alternative<seqan3::gap>(), "gap is an alternative of variant_t");
}
12 changes: 6 additions & 6 deletions test/unit/alphabet/composite/alphabet_variant_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ TEST(alphabet_variant_test, convert_by_index)
seqan3::alphabet_variant<seqan3::dna4, seqan3::dna5, seqan3::gap> u;
u = 'C'_dna5;

EXPECT_FALSE(u.is_alternative<0>());
EXPECT_TRUE(u.is_alternative<1>());
EXPECT_FALSE(u.is_alternative<2>());
EXPECT_FALSE(u.holds_alternative<0>());
EXPECT_TRUE(u.holds_alternative<1>());
EXPECT_FALSE(u.holds_alternative<2>());

EXPECT_THROW(u.convert_to<0>(), std::bad_variant_access);
EXPECT_NO_THROW(u.convert_to<1>());
Expand All @@ -304,9 +304,9 @@ TEST(alphabet_variant_test, convert_by_type)
seqan3::alphabet_variant<seqan3::dna4, seqan3::dna5, seqan3::gap> u;
u = 'C'_dna5;

EXPECT_FALSE(u.is_alternative<seqan3::dna4>());
EXPECT_TRUE(u.is_alternative<seqan3::dna5>());
EXPECT_FALSE(u.is_alternative<seqan3::gap>());
EXPECT_FALSE(u.holds_alternative<seqan3::dna4>());
EXPECT_TRUE(u.holds_alternative<seqan3::dna5>());
EXPECT_FALSE(u.holds_alternative<seqan3::gap>());

EXPECT_THROW(u.convert_to<seqan3::dna4>(), std::bad_variant_access);
EXPECT_NO_THROW(u.convert_to<seqan3::dna5>());
Expand Down