Skip to content

Commit 30d151c

Browse files
committed
Refactor checking and casting variant to type
Current implementation of `is<T>(std::variant)` and `as<T>(std::variant)` is complicated and limited only to 10 types hold in variant. They can be implemented with funtions from standard libraries: * `std::holds_alternative`, and * `std::get` That will be less complicated and will work for variadic number of types.
1 parent bef05a9 commit 30d151c

File tree

1 file changed

+22
-41
lines changed

1 file changed

+22
-41
lines changed

include/cpp2util.h

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -671,57 +671,38 @@ auto as( X const* x ) -> C const* {
671671
//-------------------------------------------------------------------------------------------------------------
672672
// std::variant is and as
673673
//
674-
template<typename... Ts>
675-
constexpr auto operator_is( std::variant<Ts...> const& x ) {
676-
return x.index();
677-
}
678-
679-
template<size_t I, typename... Ts>
680-
constexpr auto operator_as( std::variant<Ts...> const& x ) -> auto&& {
681-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
682-
return std::get<I>( x );
683-
}
684-
else {
685-
return nonesuch;
686-
}
687-
}
688674

689675
// A helper for is...
690676
template <class T, class... Ts>
691677
inline constexpr auto is_any = std::disjunction_v<std::is_same<T, Ts>...>;
692678

679+
template <typename T, typename... Types>
680+
inline constexpr std::ptrdiff_t count_t = ( std::ptrdiff_t{std::is_same_v<T, Types>} + ... );
681+
693682
template<typename T, typename... Ts>
694-
auto is( std::variant<Ts...> const& x ) {
695-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<0>(x)), T >) if (x.index() == 0) return true;
696-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<1>(x)), T >) if (x.index() == 1) return true;
697-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<2>(x)), T >) if (x.index() == 2) return true;
698-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<3>(x)), T >) if (x.index() == 3) return true;
699-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<4>(x)), T >) if (x.index() == 4) return true;
700-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<5>(x)), T >) if (x.index() == 5) return true;
701-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<6>(x)), T >) if (x.index() == 6) return true;
702-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<7>(x)), T >) if (x.index() == 7) return true;
703-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<8>(x)), T >) if (x.index() == 8) return true;
704-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<9>(x)), T >) if (x.index() == 9) return true;
705-
if constexpr (std::is_same_v< T, empty > ) {
706-
if (x.valueless_by_exception()) return true;
707-
// Need to guard this with is_any otherwise the get_if is illegal
708-
if constexpr (is_any<std::monostate, Ts...>) return std::get_if<std::monostate>(&x) != nullptr;
683+
constexpr auto is( std::variant<Ts...> const& x ) {
684+
if constexpr (std::is_same_v< T, empty >) {
685+
if constexpr (is_any<std::monostate, Ts...>) {
686+
return std::holds_alternative<std::monostate>(x);
687+
} else {
688+
return x.valueless_by_exception();
689+
}
690+
} else {
691+
// std::holds_alternative is ill-formed if T does not appear exactly once in Ts
692+
if constexpr (count_t<T, Ts...> == 1) {
693+
return std::holds_alternative<T>(x);
694+
}
695+
return false;
709696
}
710-
return false;
711697
}
712698

713699
template<typename T, typename... Ts>
714-
auto as( std::variant<Ts...> const& x ) {
715-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<0>(x)), T >) if (x.index() == 0) return operator_as<0>(x);
716-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<1>(x)), T >) if (x.index() == 1) return operator_as<1>(x);
717-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<2>(x)), T >) if (x.index() == 2) return operator_as<2>(x);
718-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<3>(x)), T >) if (x.index() == 3) return operator_as<3>(x);
719-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<4>(x)), T >) if (x.index() == 4) return operator_as<4>(x);
720-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<5>(x)), T >) if (x.index() == 5) return operator_as<5>(x);
721-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<6>(x)), T >) if (x.index() == 6) return operator_as<6>(x);
722-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<7>(x)), T >) if (x.index() == 7) return operator_as<7>(x);
723-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<8>(x)), T >) if (x.index() == 8) return operator_as<8>(x);
724-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<9>(x)), T >) if (x.index() == 9) return operator_as<9>(x);
700+
constexpr auto as( std::variant<Ts...> const& x ) {
701+
// std::holds_alternative is ill-formed if T does not appear exactly once in Ts
702+
if constexpr (count_t<T, Ts...> == 1) {
703+
if (std::holds_alternative<T>(x))
704+
return std::get<T>(x);
705+
}
725706
throw std::bad_variant_access();
726707
}
727708

0 commit comments

Comments
 (0)