@@ -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 cpp2::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