Comment déterminer les fichiers d'en-tête à inclure?

13

Disons que j'ai le code (très simple) ci-dessous.

#include <iostream>
int main() {
    std::cout << std::stoi("12");
}

Cela compile bien sur g ++ et clang; cependant, il ne parvient pas à compiler sur MSVC avec l'erreur suivante:

erreur C2039: 'stoi': n'est pas membre de 'std'

erreur C3861: 'stoi': identifiant introuvable

Je sais que cela std::stoifait partie de l'en- <string>tête, que les deux anciens compilateurs incluent sans doute comme faisant partie de <iostream>ce dernier et non. Selon la norme C ++ [res.on.headers]

Un en-tête C ++ peut inclure d'autres en-têtes C ++.

Ce qui, pour moi, dit essentiellement que les trois compilateurs sont corrects.

Ce problème est survenu lorsqu'un de mes étudiants a soumis un travail, que l'AT a marqué comme ne compilant pas; Bien sûr, je suis allé le réparer. Cependant, je voudrais éviter de futurs incidents comme celui-ci. Alors, existe-t-il un moyen de déterminer quels fichiers d'en-tête doivent être inclus, à moins de compiler sur trois compilateurs différents pour vérifier à chaque fois?

La seule façon dont je peux penser est de s'assurer que pour chaque stdappel de fonction, une inclusion appropriée existe; mais si vous avez un code existant qui fait des milliers de lignes, cela peut être fastidieux à parcourir. Existe-t-il un moyen plus facile / meilleur d'assurer la compatibilité entre les compilateurs?

Exemple avec les trois compilateurs: https://godbolt.org/z/kJhS6U

ChrisMM
la source
6
Si vous vous souvenez que std::stoic'est pour la gestion des chaînes, vous pourriez deviner que ce <string>serait un bon en-tête à inclure. Ou vous pouvez rechercher une bonne référence qui vous le dira. Et je vous recommande de toujours inclure explicitement les fichiers d'en-tête, de sorte que vous n'ayez pas à vous fier à un comportement spécifique à l'implémentation non portable.
Un programmeur du
3
Le meilleur moyen est de se rendre à cppreference avant de se rendre sur une autre plateforme. Ils ont des trucs assez détaillés là-bas.
Siddharth
1
Incluez l'en-tête approprié au moment où vous écrivez le code. C'est à dire. au moment où vous écrivez du code qui contient std::stoi, vous vous assurez immédiatement qu'il #include <string>est également présent.
Sander De Dycker
3
Dans le cas général, c'est un problème difficile . Cependant, lorsque nous parlons de bibliothèque standard manquante, la manière normale serait en effet d'examiner tous les appels / types de fonctions utilisés.
Max Langhof
1
@ skratchi.at, les étudiants sont informés qu'ils peuvent utiliser le compilateur de leur choix, tant que leur code est conforme aux normes. Après 4 ans, c'est la première fois que cela pose problème.
ChrisMM

Réponses:

14

Existe-t-il un moyen plus facile / meilleur d'assurer la compatibilité entre les compilateurs?

Cela va toujours être un peu une corvée si vous avez une énorme base de code et que vous ne l'avez pas fait jusqu'à présent, mais une fois que vous avez terminé la correction de vos inclusions, vous pouvez vous en tenir à une procédure simple:

Lorsque vous écrivez un nouveau code qui utilise une fonctionnalité standard, comme std::stoi, branchez ce nom dans Google, accédez à l'article cppreference.com, puis regardez en haut pour voir dans quel en-tête il est défini.

Incluez-le ensuite, s'il n'est pas déjà inclus. Travail accompli!

(Vous pouvez utiliser la norme pour cela, mais ce n'est pas aussi accessible.)

Ne soyez pas tenté de tout renvoyer au profit de hacks bon marché et non portables comme <bits/stdc++.h>!


tl; dr: documentation

Courses de légèreté en orbite
la source
3
Pour être juste, une fois que vous les avez tous mémorisés et que vous n'avez plus besoin de les chercher, cela semble assez lisse
Lightness Races in Orbit
5
@JosephWood: Si vous ne savez pas à quel en-tête une fonction donnée est par cœur, il est probable que vous devriez rechercher la fonction pour vérifier vos hypothèses à ce sujet de toute façon, donc découvrir à quel en-tête elle appartient ne prend même pas plus cher temps.
DevSolar
1
Comme @JosephWood, j'espérais aussi que ceux qui ont plus d'expérience auraient une meilleure façon. Je sais quels en-têtes inclure pour la plupart des fonctions STL, mais j'espérais qu'il y aurait un moyen plus simple d'enseigner aux étudiants que de rechercher chaque fonction: P
ChrisMM
1
@ChrisMM, il existe des outils comme inclure ce que vous utilisez . Leur exactitude ne peut pas être garantie (et en effet parfois un travail manuel est nécessaire) mais ce n'est pas mal du tout.
capricieuse
4
@ChrisMM Apprendre à vos élèves à se référer à la documentation est incroyablement, incroyablement important . Des milliers affluent sur ce site chaque jour sans aucune idée terrestre qu'ils devraient le faire. L'utilisation de la documentation est le moyen le plus simple / le meilleur.
Courses de légèreté en orbite
-1

En plus d'examiner la documentation et de le faire manuellement (douloureux et long), vous pouvez utiliser certains outils qui peuvent le faire pour vous.

Vous pouvez utiliser ReSharper dans Visual Studio qui est capable d'organiser les importations (en fait VS sans ReSharper n'est pas très utilisable). Si include est manquant, il est recommandé de l'ajouter et s'il s'agit d'une ligne obsolète avec include, elle apparaît dans des couleurs plus pâles.

Ou vous pouvez utiliser CLion (disponible pour toutes les plates-formes) qui a également cette capacité (en fait, c'est la même fabrication JetBrains).

Il existe également un outil appelé inclure ce que vous avez utilisé , mais son objectif est de profiter des avantages de la déclaration avancée, je ne l'ai jamais utilisé (personnellement - mon coéquipier l'a fait pour notre projet).

Marek R
la source
clion n'inclut pas automatiquement l'en-tête correct lorsque l'autre en-tête est déjà inclus si cela fonctionne (c'est-à-dire qu'il ne suggérera pas de chaîne ici si iostream est déjà inclus) IIRC
RiaD