Когда вы можете опустить расширение файла в директиве #include?

Я играю с gmock и заметил, что он содержит эту строку:

#include <tuple>

Я ожидал tuple.h.

Когда можно исключить расширение и придает ли это директиве другое значение?


person Gordon Wilson    schedule 14.01.2009    source источник


Ответы (7)


Стандартные заголовки C++ не имеют суффикса ".h". Я полагаю, что причина в том, что существовало множество различных достандартных реализаций, которые нарушали бы стандарт. Таким образом, вместо того, чтобы требовать, чтобы поставщики изменили свой существующий заголовок «iostream.h» (например), чтобы он соответствовал стандартам (что нарушило бы их существующий пользовательский код), комитет по стандартам решил, что они уберут суффикс (что, я думаю, недопустимо). то существующая реализация уже сделана).

Таким образом, существующие нестандартные программы будут продолжать работать с использованием нестандартных библиотек поставщика. Когда пользователь хотел привести свои программы в соответствие со стандартами, одним из шагов, которые они предприняли, было изменение директивы «#include», чтобы убрать суффикс «.h».

So

#include <iostream>     // include the standard library version
#include <iostream.h>   // include a vendor specific version (which by 
                        //      now might well be the same)

Как упоминалось в других ответах, авторы нестандартных библиотек могут выбрать любое соглашение об именах, но я думаю, что они захотят продолжать использовать «.h» или «.hpp» (как это сделал Boost) по нескольким причинам:

  1. если и когда библиотека будет стандартизирована, стандартная версия не будет автоматически переопределять предыдущую, нестандартную (что, по всей вероятности, приведет к поломке пользовательского кода)
  2. кажется, существует соглашение (более или менее), что заголовки без суффикса являются стандартными библиотеками, а с суффиксом (кроме старых заголовков C) - нестандартными.

Обратите внимание, что аналогичная проблема возникла, когда комитет начал добавлять хеш-карты в STL — они обнаружили, что уже существует много (разных) hash_map реализаций, поэтому вместо того, чтобы придумать стандартную, которая ломает много чего там сегодня они называют стандартную реализацию "unordered_map". Пространства имен должны были помочь предотвратить этот тип прыжков через обручи, но, похоже, они не работали достаточно хорошо (или не использовались достаточно хорошо), чтобы позволить им использовать более естественное имя, не нарушая большого количества кода.

Обратите внимание, что для заголовков 'C' C++ позволяет включать вариант <cxxxxxx> или <xxxxxx.h>. Тот, который начинается с «c» и не имеет суффикса «.h», помещает свои объявления в пространство имен std (и, возможно, глобальное пространство имен), те, у которых есть суффикс «.h», помещают имена в глобальное пространство имен (некоторые компиляторы также поместите имена в пространство имен std - мне неясно, соответствует ли это стандарту, хотя я не вижу вреда).

person Michael Burr    schedule 14.01.2009
comment
другая (хотя, вероятно, не основная причина :)) может заключаться в том, что стандартные заголовки вообще не должны быть файлами. поэтому они могли решить отказаться от .h, потому что он предполагает расширение файла. - person Johannes Schaub - litb; 14.01.2009
comment
Это было верно начиная с ANSI C 1989, в котором есть сноска: Заголовок не обязательно является исходным файлом... Кстати, кто-нибудь знает компилятор, который делает что-то отличное от обычных исходных файлов для стандартных заголовков? - person Michael Burr; 14.01.2009
comment
@MichaelBurr Разве предварительно скомпилированные заголовки не подходят для этого? - person Peter - Reinstate Monica; 13.10.2015
comment
Правильное использование пространств имен действительно разрешило бы любые потенциальные конфликты между пользовательским кодом и кодом стандартной библиотеки, к сожалению, многие пользователи библиотеки STL имеют некоторую форму using namespace std; в своих исходных файлах, и, к сожалению (поскольку в C++ обратная совместимость является королем) Комитет решил, что это оправдывает использование другого имени. - person Tyg13; 27.03.2019

Если файл называется tuple, вам нужно #include <tuple>, если он называется tuple.h, вам нужно #include <tuple.h>

Это так просто. Вы не пропускаете ни одно расширение.

person Ferruccio    schedule 14.01.2009

Он включает в себя файл с простым названием «кортеж» — у самого файла нет расширения.

Предполагаемый стандарт для включаемых файлов C++ состоит в том, чтобы называть их без расширения .h; многие разработчики библиотек следуют этому стандарту (STL и т. д.), но некоторые — нет.

person Crashworks    schedule 14.01.2009
comment
Насколько мне известно, файлы Boost имеют расширение .hpp. - person mannicken; 14.01.2009

Ничего особенного не происходит. Файл называется просто tuple.

Причина этого... в том, что заголовки стандартных библиотек не имеют расширения файла, из-за namespaces.

Пространства имен были добавлены в стандарт C++ в конце игры со стандартом C++98, включая пространство имен std, в котором находятся все объекты стандартной библиотеки.

Когда стандартная библиотека была перенесена в пространство имен std, это означало, что весь существующий код C++ сломался, поскольку все ожидали, что библиотека будет находиться в глобальном пространстве имен. Решение состояло в том, чтобы оставить старые файлы заголовков «dot-h» в покое и предоставить библиотеку с пространством имен в файлах, не имеющих расширения.

Таким образом, старый код, который #include<iosteam.h> мог бы ожидать глобального cout, в то время как новый код мог бы #include<iostream> и ожидать std::cout.

person Drew Dormann    schedule 14.01.2009
comment
Просто нашел утверждение об обратном и хотел указать на это. Питер Беккер утверждает, что пространства имен не имеют ничего общего с именами заголовков. - person Daniel K.; 03.01.2021
comment
@ДэниелК. Я считаю, что это утверждение вырвано из контекста. Вы читали следующий комментарий Питера Беккера? Кажется, он пересказывает объяснение в этом ответе. - person Drew Dormann; 03.01.2021

Насколько я понимаю, #include tuple будет «указывать» на tuple.h.

Проверьте это: iostream vs iostream.h

person nmiller    schedule 14.01.2009
comment
Компилятор может решить, что это так. Преобразование строки в исходном коде в полный путь к файлу для ОС зависит от компилятора. Префиксы каталогов довольно распространены, а суффиксы расширений — нет. - person MSalters; 14.01.2009
comment
Ссылка не работает - person Enbugger; 14.12.2018

В дополнение к уже опубликованным прекрасным ответам следует отметить, что стандарт C++ не требует директивы «#include <iostream>» для чтения файла с именем «iostream» или даже «iostream.h». Его можно было бы назвать «пушистиком». Или может не существовать соответствующего файла, а определения будут встроены в компилятор и активированы директивой include.

person Darron    schedule 14.01.2009

Близкие,

Я думаю, что дело в следующем: #include ‹lib› всегда предшествует /lib/include к пути поиска (.h подразумевается), тогда как #include ‹lib.h› ищет только -I‹pathname ›.

Обратите внимание, что я могу ошибаться... Просто я думаю, что это работает (в Forte cc на Solaris).

person corlettk    schedule 23.05.2009
comment
Вы ошибаетесь - в стандарте C++ пути поиска не указаны. - person ; 23.05.2009
comment
Едва избежал -1, признав, что вы могли ошибаться... что вы и есть. :-) - person R.. GitHub STOP HELPING ICE; 09.07.2010