Skip to content

Commit d7a2ce5

Browse files
committed
as(): refactor of as() for std::variant
No functional changes The implementation still can handle only 20 types in variant. It will be changed in future Pull Requests.
1 parent 4a4092f commit d7a2ce5

File tree

1 file changed

+44
-105
lines changed

1 file changed

+44
-105
lines changed

include/cpp2util.h

Lines changed: 44 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,38 @@ constexpr auto variant_contains_type(std::variant<Ts...>)
804804
}
805805
}
806806

807+
template <typename C, typename X>
808+
using constness_like_t =
809+
std::conditional_t<
810+
std::is_const_v<
811+
std::remove_pointer_t<
812+
std::remove_reference_t<X>
813+
>
814+
>,
815+
std::add_const_t<C>,
816+
std::remove_const_t<C>
817+
>;
818+
819+
template<class T, class U>
820+
[[nodiscard]] constexpr auto&& forward_like(U&& x) noexcept
821+
{
822+
constexpr bool is_adding_const = std::is_const_v<std::remove_reference_t<T>>;
823+
if constexpr (std::is_lvalue_reference_v<T&&>)
824+
{
825+
if constexpr (is_adding_const)
826+
return std::as_const(x);
827+
else
828+
return static_cast<U&>(x);
829+
}
830+
else
831+
{
832+
if constexpr (is_adding_const)
833+
return std::move(std::as_const(x));
834+
else
835+
return std::move(x);
836+
}
837+
}
838+
807839

808840
//-----------------------------------------------------------------------
809841
//
@@ -1933,6 +1965,7 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
19331965
|| std::is_base_of_v<C, CPP2_TYPEOF(x)>
19341966
|| std::is_base_of_v<CPP2_TYPEOF(x), C>
19351967
|| requires { C{CPP2_FORWARD(x)}; }
1968+
|| specialization_of_template<CPP2_TYPEOF(x), std::variant>
19361969
)
19371970
{
19381971
if constexpr (
@@ -2005,6 +2038,17 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
20052038
}
20062039
return C{CPP2_FORWARD(x)};
20072040
}
2041+
else if constexpr (specialization_of_template<decltype(x), std::variant>) {
2042+
constness_like_t<C, decltype(x)>* ptr = nullptr;
2043+
type_find_if(CPP2_FORWARD(x), [&]<typename It>(It const&) -> bool {
2044+
if constexpr (It::index < 20) {
2045+
if constexpr (std::is_same_v< typename It::type, C >) { if (CPP2_FORWARD(x).index() == It::index) { ptr = &std::get<It::index>(x); return true; } };
2046+
}
2047+
return false;
2048+
});
2049+
if (!ptr) { Throw( std::bad_variant_access(), "'as' cast failed for 'variant'"); }
2050+
return forward_like<decltype(x)>(*ptr);
2051+
}
20082052
else {
20092053
return nonesuch;
20102054
}
@@ -2017,111 +2061,6 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
20172061

20182062
// Common internal helper
20192063
//
2020-
template<std::size_t I, typename... Ts>
2021-
constexpr auto operator_as( std::variant<Ts...> && x ) -> decltype(auto) {
2022-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
2023-
return std::get<I>( x );
2024-
}
2025-
else {
2026-
return nonesuch;
2027-
}
2028-
}
2029-
2030-
template<std::size_t I, typename... Ts>
2031-
constexpr auto operator_as( std::variant<Ts...> & x ) -> decltype(auto) {
2032-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
2033-
return std::get<I>( x );
2034-
}
2035-
else {
2036-
return nonesuch;
2037-
}
2038-
}
2039-
2040-
template<std::size_t I, typename... Ts>
2041-
constexpr auto operator_as( std::variant<Ts...> const& x ) -> decltype(auto) {
2042-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
2043-
return std::get<I>( x );
2044-
}
2045-
else {
2046-
return nonesuch;
2047-
}
2048-
}
2049-
2050-
2051-
template<typename T, typename... Ts>
2052-
auto as( std::variant<Ts...> && x ) -> decltype(auto) {
2053-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2054-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2055-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2056-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2057-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2058-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2059-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2060-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2061-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2062-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2063-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2064-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2065-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2066-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2067-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2068-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2069-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2070-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2071-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2072-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2073-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2074-
}
2075-
2076-
template<typename T, typename... Ts>
2077-
auto as( std::variant<Ts...> & x ) -> decltype(auto) {
2078-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2079-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2080-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2081-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2082-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2083-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2084-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2085-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2086-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2087-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2088-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2089-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2090-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2091-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2092-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2093-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2094-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2095-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2096-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2097-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2098-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2099-
}
2100-
2101-
template<typename T, typename... Ts>
2102-
auto as( std::variant<Ts...> const& x ) -> decltype(auto) {
2103-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2104-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2105-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2106-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2107-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2108-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2109-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2110-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2111-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2112-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2113-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2114-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2115-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2116-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2117-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2118-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2119-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2120-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2121-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2122-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2123-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2124-
}
21252064

21262065

21272066
//-------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)