¿Cómo determinar qué archivos de encabezado incluir?

13

Digamos que tengo el siguiente código (muy simple).

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

Esto compila bien tanto en g ++ como en clang; sin embargo, no se compila en MSVC con el siguiente error:

error C2039: 'stoi': no ​​es miembro de 'std'

error C3861: 'stoi': identificador no encontrado

Sé que std::stoies parte del <string>encabezado, que presumiblemente los dos compiladores anteriores incluyen como parte <iostream>y el último no. De acuerdo con el estándar C ++ [res.on.headers]

Un encabezado de C ++ puede incluir otros encabezados de C ++.

Lo cual, para mí, básicamente dice que los tres compiladores son correctos.

Este problema surgió cuando uno de mis alumnos presentó trabajo, que el TA marcó como no compilado; Por supuesto, fui y lo arreglé. Sin embargo, me gustaría evitar futuros incidentes como este. Entonces, ¿hay alguna manera de determinar qué archivos de encabezado deben incluirse, a menos que se compile en tres compiladores diferentes para verificar cada vez?

La única forma en que puedo pensar es asegurar que para cada stdllamada a la función, exista una inclusión apropiada; pero si tiene un código existente que tiene miles de líneas, puede ser tedioso buscarlo. ¿Existe una forma más fácil / mejor de garantizar la compatibilidad entre compiladores?

Ejemplo con los tres compiladores: https://godbolt.org/z/kJhS6U

ChrisMM
fuente
66
Si recuerda que std::stoies para manejar cadenas , podría adivinar que <string>sería un buen encabezado para incluir. O puede buscar una buena referencia que le dirá. Y le recomiendo que siempre incluya explícitamente los archivos de encabezado, para que no tenga que confiar en un comportamiento específico de implementación no portátil.
Algún programador amigo
3
La mejor manera es ir a cppreference antes de ir a cualquier otra plataforma. Tienen cosas bastante detalladas allí.
Siddharth
1
Incluya el encabezado apropiado en el momento en que escribe el código. Es decir. En el momento en que escribe el código que contiene, std::stoiinmediatamente se asegura de que #include <string>esté presente también.
Sander De Dycker
3
En el caso general, este es un problema difícil . Sin embargo, cuando hablamos de la falta de la biblioteca estándar incluida, la forma normal sería examinar todas las llamadas / tipos de función utilizados.
Max Langhof
1
@ skratchi.at, a los estudiantes se les dice que pueden usar el compilador que quieran, siempre que su código cumpla con los estándares. Después de 4 años, esta es la primera vez que esto ha sido un problema.
ChrisMM

Respuestas:

14

¿Existe una forma más fácil / mejor de garantizar la compatibilidad entre compiladores?

Esto siempre será una tarea difícil si tienes una gran base de código y no has estado haciendo esto hasta ahora, pero una vez que hayas arreglado tus inclusiones, puedes seguir un procedimiento simple:

Cuando escriba un código nuevo que use una característica estándar, como std::stoi, conecte ese nombre a Google, vaya al artículo de cppreference.com y luego mire la parte superior para ver en qué encabezado está definido.

Luego, inclúyalo si aún no está incluido. ¡Trabajo hecho!

( Podría usar el estándar para esto, pero no es tan accesible).

¡No caigas en la tentación de despedirlo todo a favor de trucos baratos e inportables como <bits/stdc++.h>!


tl; dr: documentación

Carreras de ligereza en órbita
fuente
3
Para ser justos, una vez que los hayas memorizado efectivamente y no necesites buscarlo más, eso se siente bastante resbaladizo
carreras de ligereza en órbita el
55
@JosephWood: si no sabe a qué encabezado corresponde una función determinada de forma rutinaria, es probable que deba buscar la función para verificar sus suposiciones de todos modos, por lo que descubrir a qué encabezado pertenece ni siquiera toma más hora.
DevSolar
1
Al igual que @JosephWood, también esperaba que aquellos con más experiencia tuvieran una mejor manera. Sé qué encabezados incluir para la mayoría de las funciones STL, pero esperaba que haya una manera más fácil de enseñar a los estudiantes que buscar cada función: P
ChrisMM
1
@ChrisMM hay herramientas como incluir-lo-que-use . No se puede garantizar su corrección (y, de hecho, a veces es necesario el trabajo manual), pero no está nada mal.
estrafalario
44
@ChrisMM Enseñar a sus alumnos a consultar la documentación es increíblemente importante . Miles de personas ingresan a este sitio todos los días sin tener la menor idea de que deberían hacerlo. Usar la documentación es la manera más fácil / mejor.
ligereza corre en órbita el
-1

Además de revisar la documentación y hacerlo manualmente (doloroso y lento), puede usar algunas herramientas que pueden hacerlo por usted.

Puede usar ReSharper en Visual Studio, que es capaz de organizar las importaciones (de hecho, VS sin ReSharper no es muy útil). Si falta incluir, recomienda agregarlo y si está obsoleto, la línea con inclusión se muestra en colores más pálidos.

O puede usar CLion (disponible para todas las plataformas) que también tiene esta capacidad (de hecho, este es el mismo fabricante de JetBrains).

También hay una herramienta llamada incluir lo que usó , pero su objetivo es aprovechar las ventajas de la declaración hacia adelante, nunca usé eso (personalmente, mi compañero de equipo lo hizo para nuestro proyecto).

Marek R
fuente
clion no incluye automáticamente el encabezado correcto cuando ya se incluye otro encabezado si funciona (es decir, no sugerirá una cadena aquí si iostream ya está incluido) IIRC
RiaD