Skip to content

Commit 1269838

Browse files
committed
Enable non-const as access to variant, closes #215
1 parent 48da7e2 commit 1269838

File tree

1 file changed

+74
-4
lines changed

1 file changed

+74
-4
lines changed

include/cpp2util.h

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ inline constexpr auto is( auto const& x, auto const& value ) -> bool
783783
struct nonesuch_ {
784784
auto operator==(auto const&) -> bool { return false; }
785785
};
786-
static nonesuch_ nonesuch;
786+
constexpr static nonesuch_ nonesuch;
787787

788788
// The 'as' cast functions are <To, From> so use that order here
789789
// If it's confusing, we can switch this to <From, To>
@@ -925,6 +925,26 @@ auto as( X const* x ) -> C const* {
925925

926926
// Common internal helper
927927
//
928+
template<size_t I, typename... Ts>
929+
constexpr auto operator_as( std::variant<Ts...> && x ) -> decltype(auto) {
930+
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
931+
return std::get<I>( x );
932+
}
933+
else {
934+
return nonesuch;
935+
}
936+
}
937+
938+
template<size_t I, typename... Ts>
939+
constexpr auto operator_as( std::variant<Ts...> & x ) -> decltype(auto) {
940+
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
941+
return std::get<I>( x );
942+
}
943+
else {
944+
return nonesuch;
945+
}
946+
}
947+
928948
template<size_t I, typename... Ts>
929949
constexpr auto operator_as( std::variant<Ts...> const& x ) -> decltype(auto) {
930950
if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
@@ -1040,7 +1060,57 @@ auto is( std::variant<Ts...> const& x ) {
10401060
}
10411061

10421062
template<typename T, typename... Ts>
1043-
auto as( std::variant<Ts...> const& x ) {
1063+
auto as( std::variant<Ts...> && x ) -> decltype(auto) {
1064+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
1065+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
1066+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
1067+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
1068+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
1069+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
1070+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
1071+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
1072+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
1073+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
1074+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<0>(x); }
1075+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<1>(x); }
1076+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<2>(x); }
1077+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<3>(x); }
1078+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<4>(x); }
1079+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<5>(x); }
1080+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<6>(x); }
1081+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<7>(x); }
1082+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<8>(x); }
1083+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<9>(x); }
1084+
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
1085+
}
1086+
1087+
template<typename T, typename... Ts>
1088+
auto as( std::variant<Ts...> & x ) -> decltype(auto) {
1089+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
1090+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
1091+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
1092+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 3>(x)), T >) { if (x.index() == 3) return operator_as<3>(x); }
1093+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 4>(x)), T >) { if (x.index() == 4) return operator_as<4>(x); }
1094+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 5>(x)), T >) { if (x.index() == 5) return operator_as<5>(x); }
1095+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 6>(x)), T >) { if (x.index() == 6) return operator_as<6>(x); }
1096+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 7>(x)), T >) { if (x.index() == 7) return operator_as<7>(x); }
1097+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 8>(x)), T >) { if (x.index() == 8) return operator_as<8>(x); }
1098+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 9>(x)), T >) { if (x.index() == 9) return operator_as<9>(x); }
1099+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<10>(x)), T >) { if (x.index() == 10) return operator_as<0>(x); }
1100+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<11>(x)), T >) { if (x.index() == 11) return operator_as<1>(x); }
1101+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<12>(x)), T >) { if (x.index() == 12) return operator_as<2>(x); }
1102+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<13>(x)), T >) { if (x.index() == 13) return operator_as<3>(x); }
1103+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<14>(x)), T >) { if (x.index() == 14) return operator_as<4>(x); }
1104+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<15>(x)), T >) { if (x.index() == 15) return operator_as<5>(x); }
1105+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<16>(x)), T >) { if (x.index() == 16) return operator_as<6>(x); }
1106+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<17>(x)), T >) { if (x.index() == 17) return operator_as<7>(x); }
1107+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<18>(x)), T >) { if (x.index() == 18) return operator_as<8>(x); }
1108+
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as<19>(x)), T >) { if (x.index() == 19) return operator_as<9>(x); }
1109+
Throw( std::bad_variant_access(), "'as' cast failed for 'variant'");
1110+
}
1111+
1112+
template<typename T, typename... Ts>
1113+
auto as( std::variant<Ts...> const& x ) -> decltype(auto) {
10441114
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 0>(x)), T >) { if (x.index() == 0) return operator_as<0>(x); }
10451115
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 1>(x)), T >) { if (x.index() == 1) return operator_as<1>(x); }
10461116
if constexpr (std::is_same_v< CPP2_TYPEOF(operator_as< 2>(x)), T >) { if (x.index() == 2) return operator_as<2>(x); }
@@ -1393,7 +1463,7 @@ auto unsafe_narrow( X&& x ) noexcept -> decltype(auto)
13931463
//-----------------------------------------------------------------------
13941464
//
13951465
template< typename C >
1396-
inline constexpr auto as_( auto&& x ) -> auto
1466+
inline constexpr auto as_( auto&& x ) -> decltype(auto)
13971467
{
13981468
if constexpr (is_narrowing_v<C, CPP2_TYPEOF(x)>) {
13991469
static_assert(
@@ -1412,7 +1482,7 @@ inline constexpr auto as_( auto&& x ) -> auto
14121482
}
14131483

14141484
template< typename C, auto x >
1415-
inline constexpr auto as_() -> auto
1485+
inline constexpr auto as_() -> decltype(auto)
14161486
{
14171487
if constexpr (requires { as<C, x>(); }) {
14181488
if constexpr( std::is_same_v< CPP2_TYPEOF((as<C, x>())), nonesuch_ > ) {

0 commit comments

Comments
 (0)