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