Disons que je l'utilise std::forward_as_tuple
pour stocker les arguments d'un appel de fonction dans un tupleSimuler std :: avant avec std :: forward_as_tuple
auto args = std::forward_as_tuple(std::forward<Args>(args)...);
Et puis je passe ce tuple par référence lvalue à une fonction qui veut pour appeler une fonction foo()
avec certains des arguments dans args
comme déterminé par un autre std::integer_sequence
. Je le fais avec std::move()
comme si
template <typename TupleArgs, std::size_t... Indices>
decltype(auto) forward_to_foo(TupleArgs&& args,
std::index_sequence<Indices...>) {
return foo(std::get<Indices>(std::move(args))...);
}
Et cela fonctionnerait parce que la version qualifiée rvalue de std::get<std::tuple>
retour std::tuple_element_t<Index, tuple<Types...>>&&
qui est une transformation identitaire du-ness de référence du std::tuple_element_t<Index, tuple<Types...>>
à cause de référence effondrement avec le &&
.
Donc, si std::tuple_element_t<Index, tuple<Types...>>
est évaluée à T&
le type retourné serait T& &&
qui est juste T&
. Raison similaire pour quand std::tuple_element_t<Index, tuple<Types...>>
renvoie T&&
et T
Ai-je raté quelque chose? Y a-t-il des cas où cela échouerait?
Eh bien, 'TupleArgs & args' devrait être' TupleArgs args' ou 'TupleArgs && args' si vous vous en déplacez. Tout le reste rend très opaque au point d'appel que l'objet transmis est muté. – Yakk
@Yakk droite, c'est quelque chose à considérer, c'est probablement mieux comme une référence de transfert. Le passer en valeur ne ferait que créer une copie des références sous-jacentes (ce qui est également bon je suppose) – Curious
Et maintenant il devrait être un 'std :: forward' au lieu d'un 'move' car' TupleArgs && 'ne doit pas être une rvalue ref. ;) (si c'est un rvalue ref, le foward fait la bonne chose de toute façon L'idée est de rendre l'exactitude du code comme une propriété locale comme raisonnable) –
Yakk