64 votes

C ++17: ne conserver que certains membres lors du déballage des tuples

Imaginons que vous ayez besoin d'appeler la méthode suivante:

std::tuple<int, int, int> foo();

En C++17, vous pouvez appeler la fonction et décompresser le tuple dans une seule ligne:

auto [a, b, c] = foo();

Maintenant, comment puis-je procéder pour stocker uniquement b et c et à jeter a?

Actuellement, je ne suis au courant de deux options:


1 - je peux utiliser une variable muette lorsque l'auto-déballage

Toutefois, la variable muette sera utilisé et il émet un avertissement, donc si je veux le silence que l'avertissement, le code sera assez désagréable à voir:

#pragma warning(push)
#pragma warning(disable:4101)
// ReSharper disable once CppDeclaratorNeverUsed
auto [_, b, c] = foo();
#pragma warning(pop)

2 - je peux stocker tout n-uplet et utiliser std::get pour récupérer la référence à l'seules les variables dont j'ai besoin. Le code est moins désagréable, mais la syntaxe est aussi moins simple.

En outre, ce code de l'augmentation de la taille par une ligne pour chaque nouvelle valeur que nous voulons garder dans le tuple.

auto tuple = foo();
int b = std::get<1>(tuple);
int c = std::get<2>(tuple);

Est-il une autre et plus méthode simple pour décompresser à seulement quelques paramètres dans un tuple?

42voto

Mansuro Points 1949

Une autre alternative consiste à utiliser un std::tie :

 int b, c;
std::tie(std::ignore, b, c) = foo();
 

Éditer

Comme mentionné dans les commentaires, cette approche présente certains problèmes:

  • Aucune inférence de type possible
  • Les objets doivent être construits avant, donc à moins que les constructeurs par défaut soient triviaux, ce n'est pas une bonne alternative.

39voto

Vittorio Romeo Points 2559

Malheureusement structuré liaisons ne sont pas explicitement le soutien de jeter des membres, et des attributs tels que [[maybe_unused]] ne peut pas être appliqué à structurées liaisons (il y a une proposition pour que: P0609: "les Attributs Structurés Liaisons").

Voici une solution possible:

auto [a, b, c] = foo();
(void) a; // unused

21voto

Barry Points 45207

Vous pouvez écrire une fonction d'assistance qui ne vous donne que des indices d'un std::tuple:

template <size_t... Is, typename Tuple>
auto take_only(Tuple&& tuple) {
    using T = std::remove_reference_t<Tuple>;

    return std::tuple<std::tuple_element_t<Is, T>...>(
        std::get<Is>(std::forward<Tuple>(tuple))...);
}

auto [b, c] = take_only<1, 2>(foo());

Ou de gouttes de la tête ou quelque chose:

template <size_t... Is, typename Tuple>
auto drop_head_impl(Tuple&& tuple, std::index_sequence<0, Is...> ) {
    return take_only<Is...>(std::forward<Tuple>(tuple));
}

template <typename Tuple>
auto drop_head(Tuple&& tuple) {
    return drop_head_impl(std::forward<Tuple>(tuple),
        std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>());
}

auto [b, c] = drop_head(foo());

Mais au-dessus des implémentations presque certainement avoir une certaine durée de vie de la complexité des questions qui sont directement en utilisant des liaisons ne veut pas le faire car il n'y a pas de durée de vie de l'extension ici.

Donc, faire ce que Vittorio dit:

auto [a, b, c] = foo();
(void)a;

5voto

Igor Akhmetov Points 932

MSVC a déjà fixé ce en VS de 15,7 Aperçu. La finale de 15,7 version devrait être disponible dans les semaines à venir. Cela signifie que la logique actuelle appuyée par les dernières versions de tous les principaux compilateurs est comme suit:

  • Si au moins l'une de la structure des liaisons de la structure de liaison de la déclaration, il n'est pas "Unused variable" avertissement sera émis pour les autres liaisons dans la même déclaration.
  • Si aucun des liaisons de la structure de liaison de déclaration sont utilisés, il est possible de couper l'avertissement à l'aide de la [[maybe_unused]] d'attribut:

    [[maybe_unused]] auto [a, b, c] = foo();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X