Может ли заголовок стандартной библиотеки C ++ включать стандартный заголовок C?

Я могу найти только в стандартном проекте N4582, что

[res.on.headers / 1] Заголовок C ++ может включать другие заголовки C ++.

Кажется, не указывается, может ли заголовок C ++ включать стандартный заголовок C.

Если это разрешено, небезопасно ли использовать глобальное имя, определенное в стандартном заголовке C, даже если этот заголовок не включен (поскольку программа может неявно включать заголовок через какой-либо стандартный заголовок C ++)?


person xskxzr    schedule 02.06.2016    source источник
comment
Раньше я делал это все время (эффективно смешивая код C и C ++ вместе), и это сработало. Разрешено ли это по стандарту, сказать не могу.   -  person    schedule 02.06.2016


Ответы (3)


Что касается вопроса, который вы задаете (конфликты имен), да, безусловно, может. Причина в том, что стандартная библиотека C ++ включает <c:::> заголовки C ++ для содержимого стандартной библиотеки C, и стандарт явно позволяет им также предоставлять имена в глобальном пространстве имен (в дополнение к обязательному предоставлению их в ::std).

Кроме того, на основе Приложения D [depr] стандарта C ++ заголовки стандартной библиотеки C (версии <:::.h>) также являются частью стандартной библиотеки C ++ (хотя и не рекомендуется). Это означает, что [res.on.headers] / 1 позволяет заголовкам C ++ включать их.

person Angew is no longer proud of SO    schedule 02.06.2016

Раздел Заголовки стандартной библиотеки D.3 C стандарта C ++ делает 26 стандартных заголовков C частью C ++. Таким образом, они являются частью C ++. Также многие другие заголовки C придерживаются общего подмножества языков (вероятно, #ifdef исключая некоторые вещи), делая их оба действительными заголовками C и C ++.

person johannes    schedule 02.06.2016

Мой ответ приходит с опозданием, но добавляет кое-что, чего нет у других, так что начнем ....

Краткий ответ: остается неясным, позволяет ли стандарт стандартный заголовок C ++ включать стандартный заголовок C.

В других ответах правильно отмечено, что стандарт С ++

  • позволяет использовать стандартный заголовок C ++
  • для включения стандартного заголовка C ++.

Что остается неясным, так это является ли стандартный заголовок C стандартным заголовком C ++. Я могу предоставить доказательства обоими способами.

Почему заголовок C действительно является заголовком C ++

В GCC 6.24 со стандартной библиотекой C GNU 2.24 следующий тест не может быть скомпилирован.

#include <iostream>

namespace {
    const int printf {42};
}

int main()
{
    std::cout << printf << "\n";
    return 0;
}

Компилятор жалуется, что «ссылка на printf неоднозначна», несмотря на то, что в тесте отсутствует явное #include <cstdio>.

Мнение разработчиков такого крупного компилятора и стандартной библиотеки, как GCC и GNU, вряд ли следует игнорировать.

Другие ответы дали дополнительные причины, по которым мне не нужно здесь повторяться.

Почему заголовок C не является заголовком C ++

Стандарт C ++ 17 (черновик здесь), сноска 166, гласит:

[T] Заголовки C ++ для средств библиотеки C могут ... определять имена в глобальном пространстве имен.

Если бы заголовки C были заголовками C ++, тогда это было бы странным способом написать такую ​​сноску, не так ли? Вместо этого можно было бы ожидать, что сноска будет начинаться такими словами, как «Заголовки не <*.h> C ++ для средств библиотеки C ...»

Последнее наблюдение неубедительно, но в [res.on.headers] стандарт также гласит:

Заголовки стандартной библиотеки C должны включать только соответствующий заголовок стандартной библиотеки C ++ ....

Опять же, если бы заголовки C были заголовками C ++ по оценке человека, написавшего слова, то это могло бы показаться странным способом их написания.

Вывод: неоднозначный

К сожалению, как и другие ответчики, я не могу найти четкого ответа в стандартном тем или ином случае. В отличие от других респондентов, я бы пришел к выводу, что ответ остается неоднозначным. Соответствующие разделы в стандарте включают [content], [res.on.headers] и [depr.c.headers].

Мнение

Если вы хотите знать, какая альтернатива, на мой взгляд, имеет преимущественную силу, я бы не согласился с другими ответами. По указанным причинам я бы сказал, что стандарт не позволяет стандартному заголовку C ++ включать стандартный заголовок C. Такое включение противоречит обычному использованию C ++, во всяком случае, поскольку такое включение затрудняет использование анонимных глобальных пространств имен. [Измените printf на foo в моем тесте, а затем спросите, что произойдет, если будущая стандартная библиотека C добавит функцию foo(). Такой эксперимент иллюстрирует проблему.]

С другой стороны, бороться со своим набором инструментов довольно бессмысленно, не так ли? До тех пор, пока не прояснится будущая версия C ++, я, например, хочу избегать анонимных глобальных пространств имен в исходных файлах, которые включают заголовки стандартных библиотек.

Я подозреваю, что, поскольку стандарт устарел от старых стилей, в которых используются стандартные заголовки C, комитет по стандартам, возможно, не слишком много думает о том, как исправить проблемы со старым стилем тем временем. Возможно, модули C ++ 20 дадут отличное решение. Мы увидим.

person thb    schedule 11.03.2019