Wie bestimme ich, welche Header-Dateien eingeschlossen werden sollen?

13

Angenommen, ich habe den folgenden (sehr einfachen) Code.

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

Dies lässt sich sowohl in g ++ als auch in clang gut kompilieren. Es kann jedoch nicht mit folgendem Fehler auf MSVC kompiliert werden:

Fehler C2039: 'stoi': ist kein Mitglied von 'std'

Fehler C3861: 'stoi': Kennung nicht gefunden

Ich weiß, dass dies std::stoiTeil des <string>Headers ist, den vermutlich die beiden ersteren Compiler als Teil enthalten <iostream>und der letztere nicht. Nach dem C ++ Standard [res.on.headers]

Ein C ++ - Header kann andere C ++ - Header enthalten.

Was für mich im Grunde bedeutet, dass alle drei Compiler korrekt sind.

Dieses Problem trat auf, als einer meiner Schüler Arbeiten einreichte, die der TA als nicht kompilierend markierte. Ich habe es natürlich repariert. Ich möchte jedoch zukünftige Vorfälle wie diese verhindern. Gibt es also eine Möglichkeit zu bestimmen, welche Header-Dateien enthalten sein sollen, ohne auf drei verschiedenen Compilern zu kompilieren, die jedes Mal überprüft werden müssen?

Ich kann mir nur vorstellen, dass für jeden stdFunktionsaufruf ein geeignetes Include vorhanden ist. Wenn Sie jedoch Code haben, der Tausende von Zeilen lang ist, kann das Durchsuchen mühsam sein. Gibt es eine einfachere / bessere Möglichkeit, die Cross-Compiler-Kompatibilität sicherzustellen?

Beispiel mit den drei Compilern: https://godbolt.org/z/kJhS6U

ChrisMM
quelle
6
Wenn Sie sich daran erinnern, dass dies std::stoifür die Behandlung von Zeichenfolgen vorgesehen ist, können Sie davon ausgehen, dass <string>dies ein guter Header wäre. Oder Sie könnten nach einer guten Referenz suchen, die Ihnen sagt. Und ich empfehle, dass Sie die Header-Dateien immer explizit einschließen, damit Sie sich nicht auf ein nicht portables implementierungsspezifisches Verhalten verlassen müssen.
Einige Programmierer Typ
3
Am besten gehen Sie zu cppreference, bevor Sie zu einer anderen Plattform wechseln . Sie haben dort ziemlich detaillierte Sachen.
Siddharth
1
Fügen Sie den entsprechenden Header ein, sobald Sie den Code schreiben. Dh. Sobald Sie Code schreiben, der enthält, stellen std::stoiSie sofort sicher, dass auch dieser #include <string>vorhanden ist.
Sander De Dycker
3
Im allgemeinen Fall ist dies ein schwieriges Problem . Wenn es sich jedoch um fehlende Standardbibliotheks-Includes handelt, besteht der normale Weg darin, alle verwendeten Funktionsaufrufe / -typen zu untersuchen.
Max Langhof
1
@ skratchi.at wird den Schülern mitgeteilt, dass sie jeden gewünschten Compiler verwenden können, sofern ihr Code dem Standard entspricht. Nach 4 Jahren ist dies das erste Mal, dass dies ein Problem darstellt.
ChrisMM

Antworten:

14

Gibt es eine einfachere / bessere Möglichkeit, die Cross-Compiler-Kompatibilität sicherzustellen?

Dies wird immer ein bisschen mühsam sein, wenn Sie eine riesige Codebasis haben und dies bisher noch nicht getan haben, aber sobald Sie Ihre Includes repariert haben, können Sie sich an ein einfaches Verfahren halten:

Wenn Sie neuen Code schreiben, der eine Standardfunktion verwendet, z. B. std::stoidiesen Namen in Google einbinden, den Artikel cppreference.com lesen und oben nachsehen, in welchem ​​Header er definiert ist.

Fügen Sie das dann hinzu, falls es nicht bereits enthalten ist. Job erledigt!

(Sie könnten den Standard dafür verwenden, aber das ist nicht so zugänglich.)

Seien Sie nicht versucht, alles zugunsten billiger, nicht portierbarer Hacks wie <bits/stdc++.h>!


tl; dr: Dokumentation

Leichtigkeitsrennen im Orbit
quelle
3
Um fair zu sein, wenn Sie sie alle effektiv auswendig gelernt haben und sie nicht mehr nachschlagen müssen, fühlt sich das ziemlich schick an
Lightness Races in Orbit
5
@JosephWood: Wenn Sie nicht wissen, welcher Header eine bestimmte Funktion auswendig kann, sollten Sie die Funktion wahrscheinlich nachschlagen, um Ihre Annahmen zu überprüfen. Wenn Sie also herausfinden, zu welchem ​​Header sie gehört, ist dies nicht einmal mehr erforderlich Zeit.
DevSolar
1
Wie @JosephWood hoffte ich auch, dass diejenigen mit mehr Erfahrung einen besseren Weg hatten. Ich weiß, welche Header für die meisten STL-Funktionen enthalten sein sollen, hoffte jedoch, dass es einen einfacheren Weg gibt, Schüler zu unterrichten, als jede Funktion
nachzuschlagen
1
@ ChrisMM gibt es Tools wie include-what-you-use . Ihre Richtigkeit kann nicht garantiert werden (und manchmal ist manuelle Arbeit notwendig), aber es ist überhaupt nicht schlecht.
freakish
4
@ChrisMM Es ist unglaublich wichtig, Ihren Schülern beizubringen, sich auf die Dokumentation zu beziehen . Tausende strömen jeden Tag auf diese Seite, ohne die irdische Idee zu haben, dass sie es tun sollten. Die Verwendung der Dokumentation ist der einfachere / bessere Weg.
Leichtigkeitsrennen im Orbit
-1

Neben der Überprüfung der Dokumentation und der manuellen Ausführung (schmerzhaft und zeitaufwändig) können Sie einige Tools verwenden, die dies für Sie tun können.

Sie können ReSharper in Visual Studio verwenden, das Importe organisieren kann (tatsächlich ist VS ohne ReSharper nicht sehr brauchbar). Wenn include fehlt, wird empfohlen, es hinzuzufügen, und wenn es veraltet ist, wird die Zeile mit include in helleren Farben angezeigt.

Oder Sie können CLion (für alle Plattformen verfügbar) verwenden, das ebenfalls über diese Funktion verfügt (tatsächlich handelt es sich um JetBrains der gleichen Hersteller).

Es gibt auch ein Tool namens include, was Sie verwendet haben , aber das Ziel ist es, die Vorteile der Vorwärtsdeklaration zu nutzen. Ich habe das nie verwendet (persönlich - mein Teamkollege hat das für unser Projekt getan).

Marek R.
quelle
Clion schließt den korrekten Header nicht automatisch aus, wenn bereits ein anderer Header enthalten ist, wenn er funktioniert (dh er schlägt hier keinen String vor, wenn iostream bereits enthalten ist). IIRC
RiaD