Skip to content

Commit a3c8f14

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 c664b07 commit a3c8f14

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
//
@@ -1906,6 +1938,7 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
19061938
|| std::is_base_of_v<C, CPP2_TYPEOF(x)>
19071939
|| std::is_base_of_v<CPP2_TYPEOF(x), C>
19081940
|| requires { C{CPP2_FORWARD(x)}; }
1941+
|| specialization_of_template<CPP2_TYPEOF(x), std::variant>
19091942
)
19101943
{
19111944
if constexpr (
@@ -1978,6 +2011,17 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
19782011
}
19792012
return C{CPP2_FORWARD(x)};
19802013
}
2014+
else if constexpr (specialization_of_template<decltype(x), std::variant>) {
2015+
constness_like_t<C, decltype(x)>* ptr = nullptr;
2016+
type_find_if(CPP2_FORWARD(x), [&]<typename It>(It const&) -> bool {
2017+
if constexpr (It::index < 20) {
2018+
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; } };
2019+
}
2020+
return false;
2021+
});
2022+
if (!ptr) { Throw( std::bad_variant_access(), "'as' cast failed for 'variant'"); }
2023+
return cpp2::forward_like<decltype(x)>(*ptr);
2024+
}
19812025
else {
19822026
return nonesuch;
19832027
}
@@ -1990,111 +2034,6 @@ auto as(auto&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)
19902034

19912035
// Common internal helper
19922036
//
1993-
template<std::size_t I, typename... Ts>
1994-
constexpr auto operator_as( std::variant<Ts...> && x ) -> decltype(auto) {
1995-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
1996-
return std::get<I>( x );
1997-
}
1998-
else {
1999-
return nonesuch;
2000-
}
2001-
}
2002-
2003-
template<std::size_t I, typename... Ts>
2004-
constexpr auto operator_as( std::variant<Ts...> & x ) -> decltype(auto) {
2005-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
2006-
return std::get<I>( x );
2007-
}
2008-
else {
2009-
return nonesuch;
2010-
}
2011-
}
2012-
2013-
template<std::size_t I, typename... Ts>
2014-
constexpr auto operator_as( std::variant<Ts...> const& x ) -> decltype(auto) {
2015-
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
2016-
return std::get<I>( x );
2017-
}
2018-
else {
2019-
return nonesuch;
2020-
}
2021-
}
2022-
2023-
2024-
template<typename T, typename... Ts>
2025-
auto as( std::variant<Ts...> && x ) -> decltype(auto) {
2026-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2027-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2028-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2029-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2030-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2031-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2032-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2033-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2034-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2035-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2036-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2037-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2038-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2039-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2040-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2041-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2042-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2043-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2044-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2045-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2046-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2047-
}
2048-
2049-
template<typename T, typename... Ts>
2050-
auto as( std::variant<Ts...> & x ) -> decltype(auto) {
2051-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2052-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2053-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2054-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2055-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2056-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2057-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2058-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2059-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2060-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2061-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2062-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2063-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2064-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2065-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2066-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2067-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2068-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2069-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2070-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2071-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2072-
}
2073-
2074-
template<typename T, typename... Ts>
2075-
auto as( std::variant<Ts...> const& x ) -> decltype(auto) {
2076-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
2077-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
2078-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
2079-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
2080-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
2081-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
2082-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
2083-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
2084-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
2085-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
2086-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<10>(x); }
2087-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<11>(x); }
2088-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<12>(x); }
2089-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<13>(x); }
2090-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<14>(x); }
2091-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<15>(x); }
2092-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<16>(x); }
2093-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<17>(x); }
2094-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<18>(x); }
2095-
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<19>(x); }
2096-
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
2097-
}
20982037

20992038

21002039
//-------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)