@@ -655,6 +655,11 @@ concept specialization_of_template_type_and_nttp = requires (X x) {
655655 { specialization_of_template_helper<C>(std::forward<X>(x)) } -> std::same_as<std::true_type>;
656656};
657657
658+ template <typename X>
659+ concept boolean_testable = std::convertible_to<X, bool > && requires (X&& x) {
660+ { !std::forward<X>(x) } -> std::convertible_to<bool >;
661+ };
662+
658663template <typename X>
659664concept dereferencable = requires (X x) { *x; };
660665
@@ -738,6 +743,67 @@ auto pointer_eq(T const* a, T const* b) {
738743 return std::compare_three_way{}(a, b) == std::strong_ordering::equal;
739744}
740745
746+ // -----------------------------------------------------------------------
747+ //
748+ // A type_find_if for iterating over types in parameter packs
749+ //
750+ // Note: the current implementation is a workaround for clang-12 internal error.
751+ // Original implementation does not need type_it and is implemented
752+ // using lambda with explicit parameter type list in the following way:
753+ //
754+ // template <typename... Ts, typename F>
755+ // constexpr auto type_find_if(F&& fun)
756+ // {
757+ // std::size_t found = std::variant_npos;
758+ // [&]<std::size_t... Is>(std::index_sequence<Is...>){
759+ // if constexpr ((requires { {CPP2_FORWARD(fun).template operator()<Is, Ts>()} -> std::convertible_to<bool>;} && ...)) {
760+ // (((CPP2_FORWARD(fun).template operator()<Is, Ts>()) && (found = Is, true)) || ...);
761+ // }
762+ // }(std::index_sequence_for<Ts...>());
763+ // return found;
764+ // }
765+ //
766+ // The workaround is not needed in gcc-12.1+, clang-13+, msvc 19.29+
767+ //
768+ // Note2: the internal if constexpr could have else with static_assert.
769+ // Unfortunatelly I cannot make it work on MSVC.
770+ //
771+ // -----------------------------------------------------------------------
772+ //
773+ template <std::size_t Index, typename T>
774+ struct type_it {
775+ using type = T;
776+ inline static const std::size_t index = Index;
777+ };
778+
779+ template <typename ... Ts, typename F>
780+ constexpr auto type_find_if (F&& fun)
781+ {
782+ std::size_t found = std::variant_npos;
783+ [&]<std::size_t ... Is>(std::index_sequence<Is...>){
784+ if constexpr ((requires { {CPP2_FORWARD (fun)(type_it<Is, Ts>{})} -> boolean_testable;} && ...)) {
785+ ((CPP2_FORWARD (fun)(type_it<Is, Ts>{}) && (found = Is, true )) || ...);
786+ }
787+ }(std::index_sequence_for<Ts...>());
788+ return found;
789+ }
790+
791+ template <typename F, template <typename ...> class C , typename ... Ts>
792+ constexpr auto type_find_if (C<Ts...> const &, F&& fun)
793+ {
794+ return type_find_if<Ts...>(CPP2_FORWARD (fun));
795+ }
796+
797+ template <typename T, typename ... Ts>
798+ constexpr auto variant_contains_type (std::variant<Ts...>)
799+ {
800+ if constexpr (is_any<T, Ts...>) {
801+ return std::true_type{};
802+ } else {
803+ return std::false_type{};
804+ }
805+ }
806+
741807
742808// -----------------------------------------------------------------------
743809//
@@ -1650,6 +1716,28 @@ constexpr auto is( X const& x ) -> auto {
16501716 {
16511717 return Dynamic_cast<C const *>(&x) != nullptr ;
16521718 }
1719+ else if constexpr (
1720+ specialization_of_template<X, std::variant>
1721+ )
1722+ {
1723+ if (x.valueless_by_exception ()) {
1724+ return std::is_same_v<C, empty>;
1725+ }
1726+ if constexpr (
1727+ std::is_same_v<C, empty>
1728+ )
1729+ {
1730+ if constexpr (requires { {variant_contains_type<std::monostate>(std::declval<X>())} -> std::same_as<std::true_type>; }) {
1731+ return std::get_if<std::monostate>(&x) != nullptr ;
1732+ }
1733+ }
1734+ return type_find_if (x, [&]<typename It>(It const &) -> bool {
1735+ if constexpr (It::index < 20 ) {
1736+ if (x.index () == It::index) { return std::is_same_v<C, std::variant_alternative_t <It::index, X>>;}
1737+ }
1738+ return false ;
1739+ }) != std::variant_npos;
1740+ }
16531741 else if constexpr (
16541742 (
16551743 std::is_same_v<X, std::nullptr_t >
@@ -1700,6 +1788,20 @@ inline constexpr auto is( auto const& x, auto&& value ) -> bool
17001788 else if constexpr (requires { bool {x == value}; }) {
17011789 return x == value;
17021790 }
1791+ else if constexpr (specialization_of_template<decltype (x), std::variant> ) {
1792+ return type_find_if (x, [&]<typename It>(It const &) -> bool {
1793+ if constexpr (It::index < 20 ) { // TODO: remove after refactor
1794+ if (x.index () == It::index) {
1795+ if constexpr (valid_predicate<decltype (value), decltype (std::get<It::index>(x))>) {
1796+ return value (std::get<It::index>(x));
1797+ } else if constexpr ( requires { bool {std::get<It::index>(x) == value}; } ) {
1798+ return std::get<It::index>(x) == value;
1799+ }
1800+ }
1801+ }
1802+ return false ;
1803+ }) != std::variant_npos;
1804+ }
17031805 return false ;
17041806}
17051807
@@ -1919,106 +2021,6 @@ constexpr auto operator_as( std::variant<Ts...> const& x ) -> decltype(auto) {
19192021}
19202022
19212023
1922- // is Type
1923- //
1924- template <typename ... Ts>
1925- constexpr auto operator_is ( std::variant<Ts...> const & x ) {
1926- return x.index ();
1927- }
1928-
1929- template <typename T, typename ... Ts>
1930- auto is ( std::variant<Ts...> const & x );
1931-
1932-
1933- // is Value
1934- //
1935- template <typename ... Ts>
1936- constexpr auto is ( std::variant<Ts...> const & x, auto && value ) -> bool
1937- {
1938- // Predicate case
1939- if constexpr (requires { bool { value (operator_as< 0 >(x)) }; }) { if (x.index () == 0 ) return value (operator_as< 0 >(x)); }
1940- else if constexpr (requires { bool { value (operator_as< 1 >(x)) }; }) { if (x.index () == 1 ) return value (operator_as< 1 >(x)); }
1941- else if constexpr (requires { bool { value (operator_as< 2 >(x)) }; }) { if (x.index () == 2 ) return value (operator_as< 2 >(x)); }
1942- else if constexpr (requires { bool { value (operator_as< 3 >(x)) }; }) { if (x.index () == 3 ) return value (operator_as< 3 >(x)); }
1943- else if constexpr (requires { bool { value (operator_as< 4 >(x)) }; }) { if (x.index () == 4 ) return value (operator_as< 4 >(x)); }
1944- else if constexpr (requires { bool { value (operator_as< 5 >(x)) }; }) { if (x.index () == 5 ) return value (operator_as< 5 >(x)); }
1945- else if constexpr (requires { bool { value (operator_as< 6 >(x)) }; }) { if (x.index () == 6 ) return value (operator_as< 6 >(x)); }
1946- else if constexpr (requires { bool { value (operator_as< 7 >(x)) }; }) { if (x.index () == 7 ) return value (operator_as< 7 >(x)); }
1947- else if constexpr (requires { bool { value (operator_as< 8 >(x)) }; }) { if (x.index () == 8 ) return value (operator_as< 8 >(x)); }
1948- else if constexpr (requires { bool { value (operator_as< 9 >(x)) }; }) { if (x.index () == 9 ) return value (operator_as< 9 >(x)); }
1949- else if constexpr (requires { bool { value (operator_as<10 >(x)) }; }) { if (x.index () == 10 ) return value (operator_as<10 >(x)); }
1950- else if constexpr (requires { bool { value (operator_as<11 >(x)) }; }) { if (x.index () == 11 ) return value (operator_as<11 >(x)); }
1951- else if constexpr (requires { bool { value (operator_as<12 >(x)) }; }) { if (x.index () == 12 ) return value (operator_as<12 >(x)); }
1952- else if constexpr (requires { bool { value (operator_as<13 >(x)) }; }) { if (x.index () == 13 ) return value (operator_as<13 >(x)); }
1953- else if constexpr (requires { bool { value (operator_as<14 >(x)) }; }) { if (x.index () == 14 ) return value (operator_as<14 >(x)); }
1954- else if constexpr (requires { bool { value (operator_as<15 >(x)) }; }) { if (x.index () == 15 ) return value (operator_as<15 >(x)); }
1955- else if constexpr (requires { bool { value (operator_as<16 >(x)) }; }) { if (x.index () == 16 ) return value (operator_as<16 >(x)); }
1956- else if constexpr (requires { bool { value (operator_as<17 >(x)) }; }) { if (x.index () == 17 ) return value (operator_as<17 >(x)); }
1957- else if constexpr (requires { bool { value (operator_as<18 >(x)) }; }) { if (x.index () == 18 ) return value (operator_as<18 >(x)); }
1958- else if constexpr (requires { bool { value (operator_as<19 >(x)) }; }) { if (x.index () == 19 ) return value (operator_as<19 >(x)); }
1959- else if constexpr (std::is_function_v<decltype (value)> || requires { &value.operator (); }) {
1960- return false ;
1961- }
1962-
1963- // Value case
1964- else {
1965- if constexpr (requires { bool { operator_as< 0 >(x) == value }; }) { if (x.index () == 0 ) return operator_as< 0 >(x) == value; }
1966- if constexpr (requires { bool { operator_as< 1 >(x) == value }; }) { if (x.index () == 1 ) return operator_as< 1 >(x) == value; }
1967- if constexpr (requires { bool { operator_as< 2 >(x) == value }; }) { if (x.index () == 2 ) return operator_as< 2 >(x) == value; }
1968- if constexpr (requires { bool { operator_as< 3 >(x) == value }; }) { if (x.index () == 3 ) return operator_as< 3 >(x) == value; }
1969- if constexpr (requires { bool { operator_as< 4 >(x) == value }; }) { if (x.index () == 4 ) return operator_as< 4 >(x) == value; }
1970- if constexpr (requires { bool { operator_as< 5 >(x) == value }; }) { if (x.index () == 5 ) return operator_as< 5 >(x) == value; }
1971- if constexpr (requires { bool { operator_as< 6 >(x) == value }; }) { if (x.index () == 6 ) return operator_as< 6 >(x) == value; }
1972- if constexpr (requires { bool { operator_as< 7 >(x) == value }; }) { if (x.index () == 7 ) return operator_as< 7 >(x) == value; }
1973- if constexpr (requires { bool { operator_as< 8 >(x) == value }; }) { if (x.index () == 8 ) return operator_as< 8 >(x) == value; }
1974- if constexpr (requires { bool { operator_as< 9 >(x) == value }; }) { if (x.index () == 9 ) return operator_as< 9 >(x) == value; }
1975- if constexpr (requires { bool { operator_as<10 >(x) == value }; }) { if (x.index () == 10 ) return operator_as<10 >(x) == value; }
1976- if constexpr (requires { bool { operator_as<11 >(x) == value }; }) { if (x.index () == 11 ) return operator_as<11 >(x) == value; }
1977- if constexpr (requires { bool { operator_as<12 >(x) == value }; }) { if (x.index () == 12 ) return operator_as<12 >(x) == value; }
1978- if constexpr (requires { bool { operator_as<13 >(x) == value }; }) { if (x.index () == 13 ) return operator_as<13 >(x) == value; }
1979- if constexpr (requires { bool { operator_as<14 >(x) == value }; }) { if (x.index () == 14 ) return operator_as<14 >(x) == value; }
1980- if constexpr (requires { bool { operator_as<15 >(x) == value }; }) { if (x.index () == 15 ) return operator_as<15 >(x) == value; }
1981- if constexpr (requires { bool { operator_as<16 >(x) == value }; }) { if (x.index () == 16 ) return operator_as<16 >(x) == value; }
1982- if constexpr (requires { bool { operator_as<17 >(x) == value }; }) { if (x.index () == 17 ) return operator_as<17 >(x) == value; }
1983- if constexpr (requires { bool { operator_as<18 >(x) == value }; }) { if (x.index () == 18 ) return operator_as<18 >(x) == value; }
1984- if constexpr (requires { bool { operator_as<19 >(x) == value }; }) { if (x.index () == 19 ) return operator_as<19 >(x) == value; }
1985- }
1986- return false ;
1987- }
1988-
1989-
1990- // as
1991- //
1992- template <typename T, typename ... Ts>
1993- auto is ( std::variant<Ts...> const & x ) {
1994- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 0 >(x)), T >) { if (x.index () == 0 ) return true ; }
1995- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 1 >(x)), T >) { if (x.index () == 1 ) return true ; }
1996- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 2 >(x)), T >) { if (x.index () == 2 ) return true ; }
1997- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 3 >(x)), T >) { if (x.index () == 3 ) return true ; }
1998- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 4 >(x)), T >) { if (x.index () == 4 ) return true ; }
1999- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 5 >(x)), T >) { if (x.index () == 5 ) return true ; }
2000- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 6 >(x)), T >) { if (x.index () == 6 ) return true ; }
2001- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 7 >(x)), T >) { if (x.index () == 7 ) return true ; }
2002- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 8 >(x)), T >) { if (x.index () == 8 ) return true ; }
2003- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 9 >(x)), T >) { if (x.index () == 9 ) return true ; }
2004- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<10 >(x)), T >) { if (x.index () == 10 ) return true ; }
2005- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<11 >(x)), T >) { if (x.index () == 11 ) return true ; }
2006- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<12 >(x)), T >) { if (x.index () == 12 ) return true ; }
2007- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<13 >(x)), T >) { if (x.index () == 13 ) return true ; }
2008- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<14 >(x)), T >) { if (x.index () == 14 ) return true ; }
2009- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<15 >(x)), T >) { if (x.index () == 15 ) return true ; }
2010- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<16 >(x)), T >) { if (x.index () == 16 ) return true ; }
2011- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<17 >(x)), T >) { if (x.index () == 17 ) return true ; }
2012- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<18 >(x)), T >) { if (x.index () == 18 ) return true ; }
2013- if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<19 >(x)), T >) { if (x.index () == 19 ) return true ; }
2014- if constexpr (std::is_same_v< T, empty > ) {
2015- if (x.valueless_by_exception ()) return true ;
2016- // Need to guard this with is_any otherwise the get_if is illegal
2017- if constexpr (is_any<std::monostate, Ts...>) return std::get_if<std::monostate>(&x) != nullptr ;
2018- }
2019- return false ;
2020- }
2021-
20222024template <typename T, typename ... Ts>
20232025auto as ( std::variant<Ts...> && x ) -> decltype(auto ) {
20242026 if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 0 >(x)), T >) { if (x.index () == 0 ) return operator_as<0 >(x); }
0 commit comments