Skip to content

Commit 7090820

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 d7a7332 commit 7090820

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
@@ -653,57 +653,38 @@ auto as( X const* x ) -> C const* {
653653
//-------------------------------------------------------------------------------------------------------------
654654
// std::variant is and as
655655
//
656-
template<typename... Ts>
657-
constexpr auto operator_is( std::variant<Ts...> const& x ) {
658-
return x.index();
659-
}
660-
661-
template<size_t I, typename... Ts>
662-
constexpr auto operator_as( std::variant<Ts...> const& x ) -> auto&& {
663-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
664-
return std::get<I>( x );
665-
}
666-
else {
667-
return nonesuch;
668-
}
669-
}
670656

671657
// A helper for is...
672658
template <class T, class... Ts>
673659
inline constexpr auto is_any = std::disjunction_v<std::is_same<T, Ts>...>;
674660

661+
template <typename T, typename... Types>
662+
inline constexpr std::ptrdiff_t count_t = ( std::ptrdiff_t{std::is_same_v<T, Types>} + ... );
663+
675664
template<typename T, typename... Ts>
676-
auto is( std::variant<Ts...> const& x ) {
677-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<0>(x)), T >) if (x.index() == 0) return true;
678-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<1>(x)), T >) if (x.index() == 1) return true;
679-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<2>(x)), T >) if (x.index() == 2) return true;
680-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<3>(x)), T >) if (x.index() == 3) return true;
681-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<4>(x)), T >) if (x.index() == 4) return true;
682-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<5>(x)), T >) if (x.index() == 5) return true;
683-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<6>(x)), T >) if (x.index() == 6) return true;
684-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<7>(x)), T >) if (x.index() == 7) return true;
685-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<8>(x)), T >) if (x.index() == 8) return true;
686-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<9>(x)), T >) if (x.index() == 9) return true;
687-
if constexpr (std::is_same_v< T, empty > ) {
688-
if (x.valueless_by_exception()) return true;
689-
// Need to guard this with is_any otherwise the get_if is illegal
690-
if constexpr (is_any<std::monostate, Ts...>) return std::get_if<std::monostate>(&x) != nullptr;
665+
constexpr auto is( std::variant<Ts...> const& x ) {
666+
if constexpr (std::is_same_v< T, empty >) {
667+
if constexpr (is_any<std::monostate, Ts...>) {
668+
return std::holds_alternative<std::monostate>(x);
669+
} else {
670+
return x.valueless_by_exception();
671+
}
672+
} else {
673+
// std::holds_alternative is ill-formed if T does not appear exactly once in Ts
674+
if constexpr (count_t<T, Ts...> == 1) {
675+
return std::holds_alternative<T>(x);
676+
}
677+
return false;
691678
}
692-
return false;
693679
}
694680

695681
template<typename T, typename... Ts>
696-
auto as( std::variant<Ts...> const& x ) {
697-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<0>(x)), T >) if (x.index() == 0) return operator_as<0>(x);
698-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<1>(x)), T >) if (x.index() == 1) return operator_as<1>(x);
699-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<2>(x)), T >) if (x.index() == 2) return operator_as<2>(x);
700-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<3>(x)), T >) if (x.index() == 3) return operator_as<3>(x);
701-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<4>(x)), T >) if (x.index() == 4) return operator_as<4>(x);
702-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<5>(x)), T >) if (x.index() == 5) return operator_as<5>(x);
703-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<6>(x)), T >) if (x.index() == 6) return operator_as<6>(x);
704-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<7>(x)), T >) if (x.index() == 7) return operator_as<7>(x);
705-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<8>(x)), T >) if (x.index() == 8) return operator_as<8>(x);
706-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<9>(x)), T >) if (x.index() == 9) return operator_as<9>(x);
682+
constexpr auto as( std::variant<Ts...> const& x ) {
683+
// std::holds_alternative is ill-formed if T does not appear exactly once in Ts
684+
if constexpr (count_t<T, Ts...> == 1) {
685+
if (std::holds_alternative<T>(x))
686+
return std::get<T>(x);
687+
}
707688
throw std::bad_variant_access();
708689
}
709690

0 commit comments

Comments
 (0)