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
3 Réponses :
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:
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);
Pas une bonne idée. Tôt ou tard, vous voudriez la même chose pour un Le comité standard a conçu la boucle de plage de gamme avec une considération profonde. C'est bien mieux que std :: tuple code> et le compilateur devrait pouvoir utiliser
std :: get <> code> 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). P>
foreach code> en boucle dans d'autres langues, et c'est beaucoup plus court. Couple il avec
auto & code> et vous avez terminé! P>
"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 code> (bien non qualifié
obtenir code> plus probable) et donc le support
std :: paire < / Code> et
std :: tuple code> et tout utilisateur défini
tuple code> 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.
Comment le compilateur devinerait-il ce que
foo code> et
bar code> é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 code> ou de rechercher n'importe quelle structure avec des éléments nommés
premier code> et
second code>; 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 code> ...
@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 code> pour décompresser une paire / tuple. La syntaxe peut signifier "Définir des variables
foo code> et
bar code> avant la boucle (dans ce cas comme des wrappers de référence), et sur chaque itération do
cravate (foo, bar) = * il code> ". 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); code>. [...]
[...] 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 code> 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 code> 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 CODE> et
FIND CODE> 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 code> (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); ...} code>; 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); code>. 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 code> et
second code> ne sont pas des noms particulièrement utiles. Tout ce que vous pouvez faire est d'utiliser des affectations de type
const et code> dans les 2 premières lignes de votre boucle, comme:
pour (paire & p: m) {const int & foo = P.First; int & bar = p.seconde; } code>