2016-05-24 21 views
16

Ist Folgendes in der Norm erlaubt?Kann eine Variable als automatisch deklariert werden, die zu demselben Typ abgeleitet wurde?

#include <iostream> 

extern int a; 
auto a = 3; 

int main(int, char**) 
{ 
    std::cout << a << std::endl; 
    return 0; 
} 

clang akzeptiert den Code. g++ beschwert sich für widersprüchliche Deklaration.

+1

Sicher ist dies ein g ++ Bug –

+0

Dieser Code verursacht einen Fehler auch in MS Visual Studio 2012, mit der Fehlermeldung 'Fehler C2371: 'a': Neudefinition; verschiedene Grundtypen ". – nabroyan

+0

Was ist mit: 'extern int a; declltype (a) a; ';) – Ajay

Antwort

2

Es ist nicht viel für mich klar aus dem Standard, aber dann gibt es diese

geschrieben

Abschnitt 7.1.6.4 Auto Spezifizierer
Ein Programm, das Auto in einem Kontext verwendet nicht explizit in diesem Abschnitt erlaubt ist schlecht geformt.

Besser lesen Sie den genannten Abschnitt des Standards für alle zulässigen Kontexte.

In Anbetracht dieser, glaube ich, g ++ ist richtig und Clang ist falsch. Aber ich könnte mich irren, es könnte einen separaten Abschnitt im Standard geben, der diesen Kontext implizieren könnte, aber ich konnte ihn nicht finden.

+2

Aber 'auto a = 3;' hier ist ein explizit erlaubter Kontext. "Diese Verwendung ist erlaubt, wenn Variablen in einem Block (6.3) deklariert werden, ** im Namensraumbereich ** (3.3.6), [...]" –

+0

Vielleicht im Kontext (zu extern) ist es nicht anwendbar? Oder g ++ und clang interpretierten es anders, da die Sprache des Standards in diesem Fall ziemlich locker zu sein scheint. – Arunmu

-2

Antwort bearbeiten: Wie in den Kommentaren erwähnt. Das Problem in diesem Fall ist, dass

writting
external int a; 
auto a = 3; 

das gleiche ist wie writting

external int a; 
int a = 3; 

das heißt, Sie eine neue Definition von a haben und das verursacht einen Fehler.

Erste Antwort: Für mein Verständnis bricht dies Teile der One-Definition-Regel. Insbesondere meine ich die folgende Regel (in Bezug auf MISRA C++ 2008), die besagt, dass ein Bezeichner mit externer Verknüpfung immer nur eine Definition haben sollte. In Ihrem Beispiel haben Sie eine Definition in der aktuellen Datei (auto a = 3;) und bei extern beziehen Sie sich auch auf eine Definition in einer anderen Datei.

+6

In diesem Beispiel wird die Variable genau einmal definiert. Es gibt keine odr-Verletzung, es sei denn, "auto a" widerspricht der ursprünglichen Deklaration. Extern muss sich nicht auf die Definition in einer anderen Datei beziehen. Es bezieht sich einfach auf eine Definition in * irgendeiner * Datei. Es ist in Ordnung, eine Variable in derselben Datei zu definieren, in der sie extern deklariert wurde. – user2079303

+0

Das ist wahr. Aber wenn es keine externe Definition von 'external int a' gibt, dann wäre das dasselbe wie das Schreiben: extern int a; int a = 3; Das heißt, wir haben auch zwei Definitionen – cpow

+1

Jamboree hat den gesamten Code des Programms in der Frage gezeigt. Es gibt nur eine Definition von "a" darin. Sicher, wenn Sie weitere Definitionen hinzugefügt haben, indem Sie diese TU mit anderen TUs verknüpft haben, könnten Sie die ODR verletzen, aber ich denke nicht, dass das die Frage ist, da das nichts mit 'auto' zu tun hat. –