2016-12-18 5 views
8

Это C++ является продолжением вопроса this, который говорит, чтоЕсть ли способ узнать, какие заголовки автоматически включаются в

В C++, в отличие от C, стандартные заголовки разрешено #include других стандартных заголовков ,

Есть ли способ узнать, какие заголовки были автоматически включены, поскольку может быть сложно угадать, какие символы определены в заголовках.

Мотивация: моя домашняя работа скомпилирована и работает правильно на моем компьютере, но TA рассказала мне, что она не компилируется и не нужна пара заголовков (мьютекса и алгоритма) для компиляции. Как я могу быть уверен, что код, который я отправляю в будущем, будет пуленепробиваемым.

Мой компилятор не дает никаких предупреждений о неявной декларации. Я использую clang++ -std=c++11, чтобы скомпилировать мой код.

+1

открыт файлы заголовков, которые вы включили? Почему это так важно? –

+0

Обратите внимание, что нет необходимости иметь минимальный (и, следовательно, не переносимый!) Набор включений для стандартных заголовков; избыточные вклюают безвредны. 'cassert', я думаю, является * единственным * заголовком, который делает что-нибудь интересное, когда он включен несколько раз. – Hurkyl

+4

Никогда не полагайтесь на такие неявно включенные заголовки, это детали реализации и могут меняться в любое время. Всегда указывайте нужные функции. –

ответ

5

В стандарте перечислены символы, доступные для каждого заголовка. Нет никаких гарантий помимо этого, ни тех символов, которые явно используются, ни того, что не объявлены все символы. Вам нужно будет включить каждый заголовок для любого имени , которое вы используете. Вы должны не полагаться на косвенные включает.

С положительной стороны в стандартной библиотеке нет случая, когда для любого из стандартных заголовков библиотеки требуются дополнительные заголовки.

+0

Я C++ noob, я наивно считал, что блокировки mutex определены в заголовке потока, теперь мой компилятор автоматически включал , и я считал, что всех моих включений достаточно. Таким образом, единственный способ узнать, что я включил все заголовки, - это пройти документацию и посмотреть, где они определены, правильно ли это? –

+0

@AnuragPeshne: Да, я боюсь, что это правильно. Я попытался создать заголовки, которые делают доступными только имена, но это не так тривиально, как я надеялся. Я не знаю никакой другой попытки сделать это. –

2

Насколько я знаю, вы не можете делать то, что хотите.

Если вы попытаетесь скомпилировать свой код на нескольких примерных платформах, и он будет успешным, есть большая вероятность, что он будет компилироваться на любой другой платформе, но нет простого способа быть уверенным.

По моему опыту, заголовки MinGW C++ используют меньше #include s друг для друга. Так MinGW может стать практичным инструментом для проверки переносимости.

3

Если вы хотите знать, какие другие заголовки вытаскивают из определенного файла заголовка, самый простой способ сделать это - запустить включенный файл только на этапе препроцессора компилятора, а не полностью его компилировать. Например, если вы хотите знать, что <iostream> тянет, создать файл, содержащий только:

#include <iostream> 

затем препроцессировать его. С gcc опция -E запускает только препроцессор, не компилируя файл, и сбрасывает предварительно обработанный файл на стандартный вывод. Результирующий результат начинается с:

# 1 "t.C" 

Это мой однострочный исходный файл.

# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "/usr/include/stdc-predef.h" 1 3 4 

Видимо, gcc автоматически тянет в этом файле заголовка, независимо от того, что. Это можно игнорировать.

# 1 "<command-line>" 2 
# 1 "t.C" 
# 1 "/usr/include/c++/6.2.1/iostream" 1 3 

Хорошо, теперь мы, наконец, добраться до фактического #include заявления в моем исходном файле одной строки.Вот где мой <iostream> является:

# 36 "/usr/include/c++/6.2.1/iostream" 3 

# 37 "/usr/include/c++/6.2.1/iostream" 3 

# 1 "/usr/include/c++/6.2.1/x86_64-redhat-linux/bits/c++config.h" 1 3 

Итак, iostream сама #include s это «C++ - config.h», очевидно, внутренний заголовок компилятор заголовочный файл,.

Если я буду продолжать идти, я могу видеть, что <iostream> тянет, что не удивительно, <ios>, <type_traits>, а также заголовочные файлы, как stdio.h.

Оно не должно быть слишком трудно быстро написать небольшой скрипт, который принимает файл заголовка, запускает компилятор в фазе предварительной обработки, и производит хороший, форматированный список всех файлов заголовков, которые потянули в.

+0

Я попытался передать флаг '-E', и вы правы, он дает информацию обо всех включенных заголовках. Но он печатает много шума, что может легко путать новичка (в него включены 4 разных типа мьютекса). –

+1

Но нет никакой гарантии, что результат будет таким же, как у кого-то, использующего другую стандартную библиотеку, не так ли? Это контекст вопроса. – rici