5

Этот код стандарт соответствует?Может ли типы `cname` и` name.h` быть разными?

#include <stdio.h> 
#include <cstdio> 

int main() { 
    FILE *f1 = 0; 
    std::FILE *f2 = f1; 
} 

Объяснение: Стандарт говорит [заголовки]:

[...] содержание каждого заголовка cname должны быть такими же, как и у соответствующего заголовка name.h [... ] как бы включением. Однако в стандартной библиотеке C++ объявления [...] находятся в области пространства имен (3.3.6) пространства имен std. Неизвестно, объявлены ли эти имена впервые в области глобального пространства имен и затем они вводятся в пространство имен std с помощью явных с использованием объявлений (7.3.3).

Таким образом, в случае, если они не вводят явным использованием декларирование, они могут быть разные типа? Я не думаю, что фраза «как бы по включению» является окончательной, поскольку другая половина текста явно противоречит этому требованию, требуя, чтобы имена находились в пространстве имен std.

ответ

2

Я не верю, что пункт говорит, что они должны быть идентичны. Это просто пересмотр первоначальной (C++ 98) пункт, в котором говорилось:

Каждый C заголовок, каждый из которых имеет имя вида name.h ведет себя так, как будто каждое имя помещенного в Стандартное пространство имен библиотеки с помощью соответствующей CNAME заголовка также помещен в пределах пространства имен объема пространства имен std и сопровождается явной с использованием декларации- (7.3.3)

Это была между твердой и невозможно следовать , поскольку он противоречил существующим real C заголовки на большинстве систем. Итак, в C++ 11 текст был изменен на тот, который вы цитируете. Он позволяет реализовать его наоборот, как и они на практике сделали все вместе - используйте существующую систему, предоставленную C заголовками и импортируйте имена в пространство имен std.

Однако, есть еще один пункт говоря, что какой бы ни способ реализации делает это имена в заголовках должно означать то же самое:

Для каждого типа T из стандартной библиотеки C, типов ::T и std::T зарезервированы для реализации и, если определено, ::T должны быть идентичны std::T. ([extern.types], 17.6.4.3.4)

1

Да, они могут быть разных типов. Используйте типы C++; Заголовки C доступны только для совместимости.

Рассмотрите, если в качестве комментария к вышеприведенному ответу заголовок C++ был реализован как namespace std { #include "stdio.h" }; то ::FILE и std::FILE будут представлять разные типы.

+0

Добро пожаловать в StackOverflow. Я рекомендую сделать ваш ответ максимально приближенным, поэтому, когда есть два вопроса (как здесь: (1) Соответствует ли этот код стандарту и (2) Может ли std :: FILE и :: FILE быть разными типами) простое «Да» могло бы ввести в заблуждение. Пожалуйста, дважды проверьте, что я не исказил то, что вы намеревались сказать. –

+0

+1, потому что именно так я понимаю абзац. Однако, как правило, вы не можете реализовать его таким образом, потому что он сломается, если 'stdio.h' включает в себя охранники или эквивалент. – ybungalobill

3

Да, это стандарт конформным: FILE* объявлен в stdio.h, std::FILE* в cstdio, и две такие же из-за этого пункта вы цитируемой.

(Единственное, что это не указано, является ли, если вы только включают <cstdio>, у вас есть один и тот же FILE* в глобальном пространстве имен или нет.)


Update: Я считаю, что типы фактически то же самое на носу, и каждый тип объявляется только один раз, а затем вводится в другое пространство имен через объявление using. Единственное, что неуказано, - это тот, который стоит первым. Соответствующая противоположная стандартная цитата - D.5 (2):

Каждый заголовок C, каждый из которых имеет имя формы name.h, ведет себя так, как если бы каждое имя помещалось в пространство имен стандартной библиотеки соответствующим Заголовок cname помещается в область глобального пространства имен. Неизвестно, будут ли эти имена сначала объявлены или определены в области пространства имен (3.3.6) пространства имен std и затем будут введены в область глобального пространства имен явным использованием-деклараций (7.3.3).

В принципе, это означает, что две реализации возможны:

"C пришел первым":

// foo.h 

struct Gizmo { /* ... */ }; 

// cfoo 

#include "foo.h" 
namespace std { using ::Gizmo; } 


«C++ с C-совместимость:

// cfoo 

namespace std 
{ 
    struct Gizmo { /* ... */ }; 
} 

// foo.h 

#include <cfoo> 
using std::Gizmo; 
+1

Что именно * в этом пункте требует, чтобы они были одинаковыми? – ybungalobill

+1

@ybungalobill: «Содержимое [...] должно быть одним и тем же» - это недостаточно ясно? Составляя все это вместе, цитирует цитату, «содержимое одного и того же, но они объявлены в пространстве имен« std », а не глобальном». –

+0

Нет. Потому что, если он требует, чтобы он был объявлен в пространстве имен std и * не обязательно в глобальной области *, то контент может быть не таким. Рассмотрим, если stdio.h имеет 'struct FILE {...};' и cstdio имеет 'namespace std {struct FILE {...}; } ', является ли контент тем же или нет? – ybungalobill

 Смежные вопросы

  • Нет связанных вопросов^_^