Когда вы можете опустить расширение файла в директиве #include? - PullRequest
42 голосов
/ 14 января 2009

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

#include <tuple>

Я бы ожидал tuple.h.

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

Ответы [ 7 ]

61 голосов
/ 14 января 2009

Стандартные заголовки 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 - мне неясно, соответствует ли это стандарту, хотя я не вижу вреда).

18 голосов
/ 14 января 2009

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

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

15 голосов
/ 14 января 2009

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

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

6 голосов
/ 14 января 2009

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

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

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

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

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

4 голосов
/ 14 января 2009

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

4 голосов
/ 14 января 2009

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

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

0 голосов
/ 23 мая 2009

Народ,

Я думаю, что дело в следующем: #include allways pre pends / lib / include для пути поиска (.h ошибочно), тогда как #include ищет только -I .

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

...