Come determinare quali file di intestazione includere?


13

Supponiamo di avere il codice (molto semplice) di seguito.

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

Questo si compila bene su g ++ e clang; tuttavia, non riesce a compilare su MSVC con il seguente errore:

errore C2039: 'stoi': non è un membro di 'std'

errore C3861: 'stoi': identificatore non trovato

So che std::stoifa parte <string>dell'intestazione, che presumibilmente i due ex compilatori includono come parte <iostream>e quest'ultimo no. Secondo lo standard C ++ [res.on.headers]

Un'intestazione C ++ può includere altre intestazioni C ++.

Il che, per me, in pratica dice che tutti e tre i compilatori sono corretti.

Questo problema è emerso quando uno dei miei studenti ha presentato un lavoro, che l'AT ha contrassegnato come non compilante; Ovviamente sono andato a risolverlo. Tuttavia, vorrei prevenire incidenti futuri come questo. Quindi, c'è un modo per determinare quali file di intestazione dovrebbero essere inclusi, a meno di compilare tre diversi compilatori da controllare ogni volta?

L'unico modo a cui riesco a pensare è quello di garantire che per ogni stdchiamata di funzione, esista un'inclusione appropriata; ma se hai un codice esistente che è lungo migliaia di righe, può essere noioso cercarlo. Esiste un modo più semplice / migliore per garantire la compatibilità tra compilatori?

Esempio con i tre compilatori: https://godbolt.org/z/kJhS6U


6
Se ricordi che std::stoiè per la gestione delle stringhe potresti immaginare che <string>sarebbe una buona intestazione da includere. Oppure potresti cercare un buon riferimento che ti dirà. E ti consiglio di includere sempre esplicitamente i file di intestazione, quindi non devi fare affidamento su comportamenti specifici dell'implementazione non portatile.
Qualche programmatore, amico, il

3
Il modo migliore è andare su cppreference prima di passare a qualsiasi altra piattaforma. Lì hanno roba abbastanza dettagliata.
Siddharth,

1
Includi l'intestazione appropriata nel momento in cui scrivi il codice. Vale a dire. nel momento in cui scrivi il codice che contiene std::stoi, ti assicuri immediatamente che #include <string>sia presente anche.
Sander De Dycker,

3
Nel caso generale questo è un problema difficile . Tuttavia, quando parliamo di librerie standard mancanti, il modo normale sarebbe effettivamente esaminare tutte le chiamate / i tipi di funzione utilizzati.
Max Langhof,

1
@ skratchi.at, agli studenti viene detto che possono usare qualunque compilatore vogliano, purché il loro codice sia conforme allo standard. Dopo 4 anni, questa è la prima volta che questo è mai stato un problema.
ChrisMM,

Risposte:


14

Esiste un modo più semplice / migliore per garantire la compatibilità tra compilatori?

Questo sarà sempre un po 'fastidioso se hai una base di codice enorme e non lo hai fatto finora, ma una volta che hai finito di correggere i tuoi include, puoi seguire una semplice procedura:

Quando scrivi un nuovo codice che utilizza una funzionalità standard, ad esempio std::stoi, collega quel nome a Google, vai all'articolo cppreference.com per esso, quindi guarda in alto per vedere in quale intestazione è definita.

Quindi includilo, se non è già incluso. Lavoro fatto!

possibile utilizzare lo standard per questo, ma non è così accessibile.)

Non essere tentato di licenziare tutto a favore di hack economici, non portabili come <bits/stdc++.h>!


tl; dr: documentazione


3
Ad essere sinceri, una volta che li hai memorizzati tutti in modo efficace e non hai più bisogno di cercarli, è abbastanza fluido
Lightness Races in Orbit

5
@JosephWood: se non sai a quale intestazione una data funzione è assegnata, è probabile che dovresti cercare la funzione per ricontrollare comunque i tuoi presupposti, quindi scoprire a quale intestazione appartiene non ci vuole nemmeno un extra tempo.
DevSolar,

1
Come @JosephWood, speravo anche che quelli con più esperienza avessero un modo migliore. So quali intestazioni includere per la maggior parte delle funzioni STL, ma speravo che ci fosse un modo più semplice per insegnare agli studenti che cercare tutte le funzioni: P
ChrisMM,

1
@ChrisMM ci sono strumenti come include-what-you-use . La loro correttezza non può essere garantita (e in effetti a volte è necessario un lavoro manuale) ma non è affatto male.
strano

4
@ChrisMM Insegnare ai tuoi studenti a fare riferimento alla documentazione è incredibilmente, incredibilmente importante . Migliaia di persone si riversano su questo sito ogni giorno senza alcuna idea terrena che dovrebbero farlo. L'uso della documentazione è il modo più semplice / migliore.
Corse di leggerezza in orbita il

-1

Oltre a rivedere la documentazione e farlo manualmente (doloroso e dispendioso in termini di tempo) puoi usare alcuni strumenti che possono farlo per te.

Puoi usare ReSharper in Visual Studio che è in grado di organizzare le importazioni (in effetti VS senza ReSharper non è molto utilizzabile). Se manca l'inclusione, si consiglia di aggiungerlo e se è obsoleta la linea con l'inclusione viene mostrata in colori più chiari.

Oppure puoi usare CLion (disponibile per tutte le piattaforme) che ha anche questa capacità (in realtà è la stessa fabbricazione JetBrains).

C'è anche uno strumento chiamato include quello che hai usato , ma il suo scopo è quello di trarre vantaggio dalla dichiarazione anticipata, non l'ho mai usato (personalmente - il mio compagno di squadra lo ha fatto per il nostro progetto).


clion non include automaticamente l'intestazione corretta quando un'altra intestazione è già inclusa se funziona (cioè non suggerirà la stringa qui se iostream è già inclusa) IIRC
RiaD
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.