@@ -481,6 +481,10 @@ class out {
481
481
// when customizing is/as for std::variant
482
482
static std::nullptr_t nonesuch = nullptr ;
483
483
484
+ // For designating "holds no value" -- used only with is, not as
485
+ // TODO: Does this really warrant a new synonym? Perhaps "is void" is enough
486
+ using empty = void ;
487
+
484
488
template < typename C, typename X >
485
489
auto is ( X const & ) -> bool {
486
490
return false ;
@@ -510,6 +514,12 @@ auto is( X const* x ) -> bool {
510
514
return dynamic_cast <C const &>(x) != nullptr ;
511
515
}
512
516
517
+ template < typename C, typename X >
518
+ requires (requires (X x) { *x; X (); } && std::is_same_v<C, empty>)
519
+ auto is ( X const & x ) -> bool {
520
+ return x == X ();
521
+ }
522
+
513
523
514
524
// -------------------------------------------------------------------------------------------------------------
515
525
// Built-in as (partial)
@@ -570,6 +580,7 @@ template<typename... Ts>
570
580
constexpr auto operator_is ( std::variant<Ts...> const & x ) {
571
581
return x.index ();
572
582
}
583
+
573
584
template <size_t I, typename ... Ts>
574
585
constexpr auto operator_as ( std::variant<Ts...> const & x ) -> auto&& {
575
586
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
@@ -580,6 +591,10 @@ constexpr auto operator_as( std::variant<Ts...> const& x ) -> auto&& {
580
591
}
581
592
}
582
593
594
+ // A helper for is...
595
+ template <class T , class ... Ts>
596
+ inline constexpr auto is_any = std::disjunction_v<std::is_same<T, Ts>...> {};
597
+
583
598
template <typename T, typename ... Ts>
584
599
auto is ( std::variant<Ts...> const & x ) {
585
600
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<0 >(x)), T >) if (x.index () == 0 ) return true ;
@@ -592,6 +607,11 @@ auto is( std::variant<Ts...> const& x ) {
592
607
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<7 >(x)), T >) if (x.index () == 7 ) return true ;
593
608
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<8 >(x)), T >) if (x.index () == 8 ) return true ;
594
609
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<9 >(x)), T >) if (x.index () == 9 ) return true ;
610
+ if constexpr (std::is_same_v< T, empty > ) {
611
+ if (x.valueless_by_exception ()) return true ;
612
+ // Need to guard this with is_any otherwise the get_if is illegal
613
+ if constexpr (is_any<std::monostate, Ts...>) return std::get_if<std::monostate>(&x) != nullptr ;
614
+ }
595
615
return false ;
596
616
}
597
617
@@ -615,10 +635,15 @@ auto as( std::variant<Ts...> const& x ) {
615
635
// std::any is and as
616
636
//
617
637
template <typename T, typename X>
618
- requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any>)
638
+ requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty> )
619
639
constexpr auto is ( X const & x ) -> bool
620
640
{ return x.type () == typeid (T); }
621
641
642
+ template <typename T, typename X>
643
+ requires (std::is_same_v<X,std::any> && std::is_same_v<T,empty>)
644
+ constexpr auto is ( X const & x ) -> bool
645
+ { return !x.has_value (); }
646
+
622
647
template <typename T, typename X>
623
648
requires (!std::is_reference_v<T> && std::is_same_v<X,std::any> && !std::is_same_v<T,std::any>)
624
649
constexpr auto as ( X const & x ) -> T
@@ -633,6 +658,11 @@ template<typename T, typename X>
633
658
constexpr auto is ( X const & x ) -> bool
634
659
{ return x.has_value (); }
635
660
661
+ template <typename T, typename U>
662
+ requires std::is_same_v<T,empty>
663
+ constexpr auto is ( std::optional<U> const & x ) -> bool
664
+ { return !x.has_value (); }
665
+
636
666
template <typename T, typename X>
637
667
requires std::is_same_v<X,std::optional<T>>
638
668
constexpr auto as ( X const & x ) -> auto&&
0 commit comments