11
votes

C ++ 11 plage de gamme et carte: lisibilité

La nouvelle plage basée sur les boucles améliorent vraiment la lisibilité et sont vraiment faciles à utiliser. Cependant, considérons les éléments suivants:

tuple<T1,T2,T3> f(/*...*/) {
    /*...*/ 
    return {a,b,c};
}
auto [x,y,z] = f(); // x has type T1, y has type T2, z has type T3


11 commentaires

Comment le compilateur devinerait-il ce que foo et bar était censé faire référence à?


@Petebecker Eh bien, Foo est juste un moyen pratique de dire "Nom FOO La partie gauche de la STD :: paire". En termes absolus, il est possible de le faire au moment de la compilation: il s'agit simplement d'une commodité de notation. Je me demandais s'il était possible d'obtenir un tel effet en surcharge ou quelque chose comme ça


Oui, il est certainement possible de demander au compilateur de savoir sur std :: paire ou de rechercher n'importe quelle structure avec des éléments nommés premier et second ; C'est plutôt spécialisé et probablement pas approprié pour la normalisation. La demande suivante serait pour tous les éléments d'un tuple ...


@Pete: La demande de l'OP ne semble pas si déraisonnable (Eh bien, à l'exception de l'inférence de type peut-être): ce n'est pas si différent de l'utilisation de std :: cravate pour décompresser une paire / tuple. La syntaxe peut signifier "Définir des variables foo et bar avant la boucle (dans ce cas comme des wrappers de référence), et sur chaque itération do cravate (foo, bar) = * il ". Il pourrait également être utilisé dans d'autres endroits également, par exemple pour déballer les résultats d'une fonction renvoyant plusieurs valeurs dans un tuple: (bool inséré, définir :: itérateur IT) = myset.insert (42); . [...]


[...] Je ne vois aucune difficulté technique empêchant cela, mais je suppose que les tuples ne sont pas aussi omniprésents en C ++ comme dans d'autres langues, de sorte que ce sucre de syntaxe n'est probablement pas essentiel.


@LucTourille - std :: cravate est dans la bibliothèque, pas le compilateur. Donc, cette approche nécessite également que le compilateur connaît plus de détails sur la bibliothèque standard.


Eh bien, j'ai utilisé std :: cravate uniquement comme exemple d'une implémentation possible (qui ne fonctionne même pas), mais un compilateur serait libre de générer n'importe quel code pour fournir ce comportement. COMMENCEZ et FIND Entrez également la bibliothèque, mais ils sont utilisés pour fournir la plage de la plage de la plage de boucle.


La syntaxe pourrait être faite pour fonctionner avec n'importe quel type qui prend en charge std :: obtenir (paires, tuples, tableaux, ...). Le code de l'OP pourrait être transformé en pour (AUTO & TMP: FOOANDASCIECIÉBARS) {AUTO & FOO = STD :: Get <0> (TMP); AUTO & BAR = STD :: Get <1> (TMP); ...} ; Le code que j'ai donné pourrait être transformé de la même manière: auto & tmp = myset.insert (42); bool inséré = std :: obtenir <0> (TMP); Set :: Itérateur IT = STD :: Get <1> (TMP); . Cela permettrait même d'inférence de type.


@LucTouraille Oui, je pensais à quelque chose de ce genre. Je ne sais toujours pas si nous pouvons le faire, mais nous nous rapprochons ...


@LucTouraille: Vous devriez peut-être écrire vos pensées dans une proposition standard;)


Je comprends ce que vous dites .. premier et second ne sont pas des noms particulièrement utiles. Tout ce que vous pouvez faire est d'utiliser des affectations de type const et dans les 2 premières lignes de votre boucle, comme: pour (paire & p: m) {const int & foo = P.First; int & bar = p.seconde; }


3 Réponses :


10
votes

Il n'y a pas de telle chose que vous le souhaitez. Le plus proche consiste à déclarer des variables à l'intérieur de la boucle: xxx


0 commentaires

0
votes

Et bien sûr, vous avez toujours la possibilité d'utiliser des lambdas.

FOREACH((int a, const char* b), m, std::cout << a << b << std::endl);
FOREACH((std::pair<int, const char*> p), m, std::cout << p.first << p.second << std::endl);


0 commentaires

1
votes

Pas une bonne idée. Tôt ou tard, vous voudriez la même chose pour un std :: tuple et le compilateur devrait pouvoir utiliser std :: get <> sur le tuple < / code> automatiquement. À mon avis, votre approche vous plaise au moment seulement, et vous trouverez des problèmes avec cette approche (supposons que cela soit mis en œuvre de cette façon).

Le comité standard a conçu la boucle de plage de gamme avec une considération profonde. C'est bien mieux que foreach en boucle dans d'autres langues, et c'est beaucoup plus court. Couple il avec auto & et vous avez terminé!


4 commentaires

"Pas une bonne idée. Tôt ou tard, vous voudriez la même chose pour un STD :: Tuple et Compiler devraient pouvoir utiliser STD :: Get <> sur le tuple automatiquement." Et le problème avec c'est?


Plus de demandes du compilateur.


Comment? La façon dont je vois une telle fonctionnalité de langue serait définie pour appeler std :: get (bien non qualifié obtenir plus probable) et donc le support std :: paire < / Code> et std :: tuple et tout utilisateur défini tuple comme des conteneurs comme automatiquement.


Exactement, c'est mon point. Vous exigez trop de compilateur. Et cela ajoute une complexité, une ambiguïté, des messages d'erreur plus complexes, la lutte entre différents vendeurs de compilateur.