Як визначити, які файли заголовків включати?


13

Скажіть, у мене наведений нижче (дуже простий) код.

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

Це добре поєднує як g ++, так і кланг; однак він не може компілювати MSVC із такою помилкою:

помилка C2039: 'stoi': не є членом 'std'

помилка C3861: 'stoi': ідентифікатор не знайдено

Я знаю, що std::stoiце частина <string>заголовка, яку, імовірно, два колишні компілятори включають до складу, <iostream>а останнього - ні. Відповідно до стандарту C ++ [res.on.headers]

Заголовок C ++ може містити інші заголовки C ++.

Що, на мою думку, в основному говорить про те, що всі три компілятори є правильними.

Це питання виникло, коли один з моїх студентів подав роботу, яку ТА зазначив як некомплект; Я, звичайно, пішов і виправив це. Однак я хотів би запобігти подібним випадкам у майбутньому. Отже, чи є спосіб визначити, які файли заголовків слід включати, не маючи компіляції на трьох різних компіляторах, щоб перевіряти кожен раз?

Єдиний спосіб, який я можу придумати, - це переконатися, що для кожного stdвиклику функції існує відповідне включення; але якщо у вас є код, який становить тисячі рядків, це може бути нудно шукати. Чи є простіший / кращий спосіб забезпечити сумісність між компілятором?

Приклад із трьома компіляторами: https://godbolt.org/z/kJhS6U


6
Якщо ви пам’ятаєте, що std::stoiце для обробки рядків, ви могли б здогадатися, що <string>це буде непоганий заголовок. Або ви можете шукати хороший довідник, який вам скаже. І я рекомендую завжди чітко включати файли заголовків, тому вам не доведеться покладатися на особливості поведінки, що не переносяться.
Якийсь програміст чувак

3
Найкращий спосіб - перейти до cppreference перед тим, як перейти на будь-яку іншу платформу. У них є досить детальні речі.
Сіддхарт

1
Додайте відповідний заголовок в момент написання коду. Тобто Щойно ви пишете код, який містить std::stoi, ви відразу переконайтесь, що #include <string>він також присутній.
Сандер Де

3
У загальному випадку це складна проблема . Однак, коли ми говоримо про відсутні стандартні бібліотеки, нормальним способом було б вивчити всі використовувані виклики / типи функцій.
Макс Ленгоф

1
@ skratchi.at, студентам кажуть, що вони можуть використовувати той компілятор, який вони хочуть, якщо їх код відповідає стандарту. Через 4 роки це вперше це питання.
ChrisMM

Відповіді:


14

Чи є простіший / кращий спосіб забезпечити сумісність між компілятором?

Це завжди буде трохи клопоту, якщо у вас є величезна база даних, і ви цього ще не робили, але, як тільки ви проправили виправлення, включає, ви можете дотримуватися простої процедури:

Коли ви пишете новий код, який використовує стандартну функцію, наприклад std::stoi, підключіть це ім’я до Google, перейдіть до статті cppreference.com для цього, а потім подивіться вгорі, щоб побачити, у якому заголовку визначено.

Потім включіть це, якщо воно ще не включене. Робота виконана!

(Ви можете використовувати стандарт для цього, але це не так доступно.)

Не варто спокушатись відібрати це все на користь дешевих нерепортажних хак, як-от <bits/stdc++.h>!


tl; dr: документація


3
Якщо бути справедливим, як тільки ви їх добре запам’ятали всі і не потрібно більше їх шукати, це відчувається досить гладко
гонки легкості в орбіті

5
@JosephWood: Якщо ви не знаєте, який заголовок заданої функції є поворотом, швидше за все, ви повинні переглянути функцію, щоб все-таки двічі перевірити свої припущення, тож з’ясування, до якого заголовка належить, навіть не зайве час.
DevSolar

1
Як і @JosephWood, я також сподівався, що у тих, хто має більше досвіду, буде кращий шлях. Я знаю, які заголовки включати для більшості функцій STL, але сподівався, що існує простіший спосіб навчити студентів, ніж шукати кожну функцію: P
ChrisMM

1
@ChrisMM є такі інструменти, як " включити-що-ви" використовувати . Їх правильність не може бути гарантована (і справді іноді потрібна ручна робота), але це зовсім не погано.
химерна

4
@ChrisMM Навчання своїх учнів звертатися до документації неймовірно, неймовірно важливо . Тисячі людей щодня надходять на цей сайт, не маючи земної думки, що вони повинні це робити. Використання документації - це простіший / кращий спосіб.
Гонки легкості по орбіті

-1

Крім того, щоб переглянути документацію і зробити це вручну (болісно і забирає багато часу), ви можете використовувати деякі інструменти, які можуть зробити це для вас.

Ви можете використовувати ReSharper у Visual Studio, який здатний організовувати імпорт (адже VS без ReSharper не дуже корисний). Якщо включення відсутнє, рекомендується додати його, а якщо це застаріла лінія з включенням, відображається більш блідими кольорами.

Або ви можете використовувати CLion (доступний для всіх платформ), який також має таку можливість (адже це те саме виробництво JetBrains).

Є також інструмент під назвою включити те, що ви використовували , але його мета - скористатися перевагами прямого декларування, я ніколи цього не використовував (особисто - мій товариш по команді зробив це для нашого проекту).


clion не автоматично включає правильний заголовок, коли інший заголовок вже включений, якщо він працює (тобто. не буде запропонувати рядок тут, якщо iostream вже включений) IIRC
RiaD
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.