5

Czy ten kod jest zgodny z standardem?Czy typy w `cname` i` name.h` mogą być różnymi typami?

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

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

Objaśnienie: Norma mówi [nagłówki]:

[...] zawartość każdego nagłówka cname powinna być taka sama, jak w odpowiednim nagłówkiem name.h [... ] jakby przez włączenie. Jednak w standardowej bibliotece C++ deklaracje [...] mieszczą się w zasięgu przestrzeni nazw (3.3.6) przestrzeni nazw std. Nie określono, czy te nazwy są najpierw zadeklarowane w zasięgu globalnego obszaru nazw, a następnie są wprowadzane do przestrzeni nazw std przez jawne deklaracje-użycia (7.3.3).

Tak więc w przypadku gdy nie są wstrzykiwane przez wyraźnej używając-deklaracji, mogą być inny typ? Nie sądzę, aby zdanie "jak gdyby poprzez włączenie" było jednoznaczne, ponieważ druga połowa tekstu wyraźnie przeczy temu wymaganiu, wymagając, aby nazwy znajdowały się w przestrzeni nazw std.

Odpowiedz

2

Nie wierzę, że ustęp mówi, że muszą być identyczne. To jest tylko wersja oryginalnego (C++ 98) ustępu, który powiedział:

Każdy nagłówek C, z których każda ma swoją nazwę formularza name.h zachowuje się tak, jakby każda nazwa umieszczona w standardowe nazw biblioteki przez odpowiedni cname nagłówku jest również umieszczony w zakresie przestrzeni nazw nazw std i następuje wyraźnego używając-deklaracji (7.3.3)

było to między trudne i niemożliwe do naśladowania , ponieważ kolidowało to z istniejącym prawdziwe Nagłówki C w większości systemów. Tak więc w C++ 11 tekst został zmieniony na cytowany przez ciebie. Pozwala to na implementacje w odwrotnym kierunku, tak jak robili to w praktyce: zrobili cały czas - użyj istniejących dostarczonych nagłówków C systemu i zaimportuj nazwy do przestrzeni nazw std.

Istnieje jednak inny ustęp mówiąc, że niezależnie od sposobu wdrożenia robi to, nazwy w nagłówkach musi oznaczać to samo:

dla każdego typu T z biblioteki standardowe C, rodzaje ::T i std::T są zarezerwowane dla implementacji i, gdy są zdefiniowane, ::T muszą być identyczne z std::T. ([extern.types], 17.6.4.3.4)

1

Tak, mogą być różne. Użyj typów C++; nagłówki C istnieją tylko dla kompatybilności.

Zastanów się, czy komentarz do powyższej odpowiedzi sugeruje, że nagłówek C++ został zaimplementowany jako namespace std { #include "stdio.h" }; następnie ::FILE i std::FILE reprezentowałyby różne typy.

+0

Witamy w StackOverflow. Zalecam, aby twoja odpowiedź była jak najbardziej zamknięta, więc gdy są dwa pytania (jak tutaj: (1) czy ten kod jest zgodny ze standardem i (2) czy std :: FILE i :: FILE mogą być różnymi typami), proste "tak" może być mylące. Sprawdź dokładnie, czy nie zniekształciłem tego, co masz zamiar powiedzieć. –

+0

+1, ponieważ dokładnie tak rozumiem akapit. Zwykle jednak nie możesz tego zaimplementować w ten sposób, ponieważ przerwie się, jeśli 'stdio.h' zawiera osłony lub odpowiedniki. – ybungalobill

3

Tak, to zgodny ze standardem: FILE* jest zadeklarowana w stdio.h, std::FILE* w cstdio, a dwa są identyczne ze względu na akapit, cytowanym.

(Jedyną rzeczą, która jest nieokreślona, ​​czy, jeśli tylko zawierać <cstdio>, również mają taką samą FILE* w globalnej przestrzeni nazw, czy też nie).


Update: Wierzę, że typy w rzeczywistości takie same na nosie i że każdy typ jest zadeklarowany tylko raz, a następnie wstrzyknięty do innego obszaru nazw poprzez deklarację using. Jedyne, co nieokreślone, to to, które jest pierwsze. Odpowiedni przeciwny standardowy cytat to D.5 (2):

Każdy nagłówek C, z których każdy ma nazwę postaci nazwa.h, zachowuje się tak, jakby każda nazwa została umieszczona w standardowym obszarze nazw biblioteki według odpowiednich Nagłówek cname znajduje się w zasięgu globalnego obszaru nazw. Nie jest sprecyzowane, czy te nazwy są najpierw zadeklarowane, czy zdefiniowane w zasięgu przestrzeni nazw (3.3.6) przestrzeni nazw std, a następnie są wtryskiwane do zakresu globalnego obszaru nazw za pomocą jawnych deklaracji użycia (7.3.3).

Zasadniczo oznacza to, że możliwe są dwie implementacje:

"C było pierwsze":

// foo.h 

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

// cfoo 

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


„C++ z C-kompatybilności:

// cfoo 

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

// foo.h 

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

Co * dokładnie * w tym akapicie wymaga, aby były takie same? – ybungalobill

+1

@ybungalobill: "Zawartość [...] będzie taka sama" - czy to nie jest wystarczająco jasne? Składając wszystko razem, cytat mówi: "zawartość jest taka sama, ale są one zadeklarowane w przestrzeni nazw' std' zamiast globalnej ". –

+0

Nie. Ponieważ, jeśli wymaga tego, aby był zadeklarowany w przestrzeni nazw standardowej i * niekoniecznie w zasięgu globalnym *, zawartość może nie być taka sama. Zastanów się, czy stdio.h ma strukturę 'struct FILE {...};' a cstdio ma 'namespace std {struct FILE {...}; } ', czy treść jest taka sama, czy nie? – ybungalobill

Powiązane problemy