68
votes

La contrainte "Auto" en C ++ ne va-t-elle pas le but de celui-ci?

Dans C ++ 20, nous sommes maintenant en mesure de contraindre le mot-clé Auto pour être uniquement de type spécifique. Donc, si j'avais un code qui ressemblait à ce qui suit sans aucune contrainte:

std::integral auto something(){
  return 0;
}

int main(){
  const auto x = something();
  return x;
}

La variable x ici est déduite comme un int . Cependant, avec l'introduction de C ++ 20, nous pouvons maintenant contraindre que le auto soit un certain type comme ceci:

auto something(){
  return 1;
}

int main(){
  const auto x = something();
  return x;
}

Cela vainc le but de auto ici? Si j'ai vraiment besoin d'un std :: intégral type de données, je ne pourrais pas simplement omettre complètement le auto ? Suis-je en train de mal comprendre complètement l'utilisation de auto ?


2 commentaires

std :: intégral n'est pas un type, c'est un concept. La deuxième version du code promet simplement que tout type quelque chose () renvoie, ce sera un type qui satisfait le concept std :: intégral .


L'objectif principal de cette syntaxe concerne les paramètres, où il est clairement utile; Les types de retour et les variables ordinaires ne sont qu'un bonus.


3 Réponses :


72
votes

Une contrainte sur le type déduit auto ne signifie pas qu'il doit être un type spécifique , cela signifie qu'il doit être l'un d'un set de types qui satisfont la contrainte. Notez qu'une contrainte et un type ne sont pas la même chose, et ils ne sont pas interchangeables.

par exemple. Un concept comme std :: intégral contrainte le type déduit comme un type intégral, tels que int ou long , mais pas float , ou std :: string .

Si j'ai vraiment besoin d'un type de données std :: intégral , je ne pourrais pas simplement omettre le auto complètement?

En principe, je suppose que vous pourriez, mais cela aurait le moindre conduite à des difficultés d'analyse. par exemple. Dans une déclaration comme

foo auto f = // ...

est foo un type, ou une contrainte sur le type?

alors que dans la syntaxe actuelle , nous avons

foo f = // ...

et il ne fait aucun doute que foo est une contrainte sur le type de f .


6 commentaires

Merci, cela clarifie les choses. D'après ce que je comprends, cela a-t-il été introduit afin que le programmeur sait en quelque sorte à quoi s'attendre d'une fonction qui utilise l'auto comme type de retour? Cela rendra sûrement le code moins sujet aux insectes et plus facile à déboguer, est-ce correct?


@MaHEEPPARTAPSIGH Oui, les concepts permettent au programmeur de rendre l'intention beaucoup plus claire, ce qui est toujours agréable. Il y a un tas d'avantages supplémentaires, par exemple Les modèles de fonction qui sont instanciés incorrectement peuvent être capturés plus facilement avec des concepts; Sinon, il faudrait que la définition échoue, ce qui est désagréable (produit de mauvais messages d'erreur, par exemple)


Auto m'a fait des surprises assez intéressantes au fil des ans. Souvent, cela signifie que je n'ai pas obtenu quelque chose de bien ailleurs et que les diagnostics supplémentaires que je pourrais obtenir avec une contrainte peuvent assister à une erreur d'exécution autrement délicate ou à plusieurs pages de notes de résolution de modèle / de surcharge Nigh-Inscrit.


IIRC, les versions antérieures de la proposition / implémentation "Concepts Lite" n'avaient pas le auto dans la syntaxe. Je crois que c'est principalement pour la clarté et les concepts sont déjà leur propre catégorie syntaxique, similaire aux types.


Mec, j'ai pensé à plusieurs reprises que ce serait génial si ma langue de choix ces jours-ci (TypeScript) avait cette fonctionnalité. Ravi de voir que je ne suis pas seul là-dedans!


En pratique, cela remplit à peu près le même objectif que d'inclure un static_assert vérifier si le type de Auto F est valide par std :: intégral Les règles, comme cela se ferait généralement dans les versions de langue antérieure. Il est similaire à la contrainte de paramètres de modèle à une interface spécifique dans, par exemple, Java ou C #.



35
votes

Si j'ai vraiment besoin d'un type de données std :: intégral , je ne pourrais pas simplement omettre complètement l'auto?

Non, parce que std :: intégral n'est pas un type, c'est un concept , une contrainte sur les types (ou si vous Will, un ensemble de types plutôt qu'un seul type).

Cela ne bat-il pas le but de l'auto ici?

Le but d'origine de Auto dans C ++ 11 est le compilateur: quel que soit le type que vous déduisez . *

avec C ++ 20, Auto a un cas d'utilisation élargi - avec un concept, une contrainte sur les types. auto Still indique au compilateur: quel que soit le type que vous déduisez - mais la déduction doit également respecter la contrainte.

* - Ignorer des problèmes comme la constance, l / rvalue référence, etc.


4 commentaires

Il est intéressant de noter que contraigne donne plus (ou élargi) cas d'utilisation. Mais je suis d'accord: la contrainte donne plus de puissance car elle donne plus de garanties . :-)


@Pabloh: similaire au principe de l'héritage dans la conception orientée objet. La classe «Sub» a potentiellement plus de fonctionnalités que le parent ou la classe «super».


RE Le but d'origine de l'auto est de dire au compilateur: quel que soit le type que vous déduisez. Le but d'origine de l'auto était de dire au compilateur qu'un objet avait un stockage automatique (par opposition à enregistrer ou statique ou extern ). Le mot-clé Auto a été rarement utilisé car c'était la valeur par défaut des variables à la portée du bloc. Il n'y avait aucune raison d'utiliser l'auto parfois foo lorsque quelqueype foo signifiait la même chose. C'est ce qui a permis d'usurper le mot-clé Auto dans C ++ 11 à d'autres fins.


@DavidHammen: Édité pour clarifier que nous parlons de C ++ 11-Auto, et non de l'utilisation antérieure du mot-clé qui n'est pas lié à cette question.



4
votes

Un concept déplace souvent l'erreur plus tôt dans la compilation et rend le code un peu plus lisible (puisque le nom du concept est un indice pour le lecteur ce dont vous avez besoin d'un type).

reformulé:

Il est rare que vous utiliserez jamais une variable automatique d'une manière qu'il fonctionnera sur tous les types.

Par exemple:

auto fn(std::integral auto x) {
    return x++;
}


0 commentaires