Во-первых, некоторые машины.
alternative
- это вариант интегральных констант, которые не имеют состояния.Затем мы можем использовать их для посещения, чтобы преобразовать ограниченное значение времени выполнения в значение времени компиляции.
template<class T, T...Is>
using alternative = std::variant< std::integral_constant<T, Is>... >;
template<class List>
struct alternative_from_sequence;
template<class T, T...Is>
struct alternative_from_sequence< std::integer_sequence<T,Is...> > {
using type=alternative<T, Is...>;
};
template<class T, T Max>
using make_alternative = typename alternative_from_sequence<
std::make_integer_sequence<T, Max>
>::type;
template<class T, T Max, T Cur=Max-1>
make_alternative<T, Max> get_alternative( T value, std::integral_constant< T, Max > ={} ) {
if(Cur == 0 || value == Cur) {
return std::integral_constant<T, Cur>{};
}
if constexpr (Cur > 0)
{
return get_alternative<T, Max, Cur-1>( value );
}
}
template<class...Ts>
auto get_alternative( std::variant<Ts...> const& v ) {
return get_alternative<std::size_t, sizeof...(Ts) >( v.index() );
}
Теперь ваша актуальная проблема.Это Get
требует, чтобы вы передали свой Variant
тип:
template<class Variant, class...Ts>
Variant Get(std::tuple<Ts...> const & val, size_t index) {
auto which = get_alternative<std::size_t, sizeof...(Ts)>( index );
return std::visit( [&val]( auto i )->Variant {
return std::get<i>(val);
}, which );
}
Ваша Set
функция кажется токсичной;если типы не совпадают, практического обращения нет.Я добавлю возвращаемое значение, в котором будет указано, что присвоение не выполнено:
template<class...Ts, class...Vs>
bool Set(
std::tuple<Ts...> & val,
std::size_t index,
const std::variant<Vs...>& elem_v
) {
auto tuple_which = get_alternative<std::size_t, sizeof...(Ts)>( index );
auto variant_which = get_alternative( elem_v );
return std::visit( [&val, &elem_v](auto tuple_i, auto variant_i) {
using variant_type = std::variant_alternative_t<variant_i, std::variant<Vs...>>;
using tuple_type = std::tuple_element_t< tuple_i, std::tuple<Ts...> >;
if constexpr (!std::is_assignable<tuple_type&, variant_type const&>{}) {
return false;
} else {
std::get<tuple_i>(val) = std::get<variant_i>(elem_v);
return true;
}
}, tuple_which, variant_which );
}
Этот Set
возвращает значение false, если типы нельзя назначить.
Пример в реальном времени .