clang error: Nicht-type Template-Argument bezieht sich auf eine Funktion, die keine Verknüpfung hat - Bug?

8

Ich habe einen sehr einfachen ( C ++ 11 ) Code, der die letzte kling ( Version 3.4 trunk 187493 ) nicht kompiliert, aber GCC kompiliert fein.

Der Code (unten) instanziiert das Funktions-Template foo mit dem funktionslokalen Typ Bar und versucht dann, seine Adresse als nicht typisierten Template-Parameter für die Klasse zu verwenden. Vorlage Func :

%Vor%

clang gibt den folgenden Fehler aus:

  

Fehler : Nicht-type Template Argument bezieht sich auf die Funktion 'foo' das   hat keine Verknüpfung

Wenn ich jedoch den Typ Bar in den globalen Bereich verschiebe (indem ich ihn aus der Funktion entferne), dann kompiliert clang ihn gut, was beweist, dass der Typ funktionslokal ist.

Also ist clang richtig, um diesen Fehler zu senden, oder unterstützt der Standard das nicht (in welchem ​​Fall GCC zu milde ist, indem er es erlaubt)?

BEARBEITEN # 1: Um klar zu sein, das ist nicht ein Duplikat von Diese Frage , da 'lokale Typen nicht als Vorlagenparameter verwenden kann wurde in C ++ 11 entfernt. Allerdings ist es immer noch unklar, ob es bei der Verwendung eines lokalen Typs Auswirkungen auf die Verknüpfung gibt und ob der Aufruf korrekt ist oder nicht.

BEARBEITEN # 2: Es wurde festgestellt, dass clang den Fehler für den obigen Code korrekt ausgegeben hat (siehe Antwort von @jxh), aber dass falsch auch einen Fehler ausgibt für den folgenden Code (mit using -Deklaration wurde von foo<Bar>() scope in main() scope verschoben): %Vor%     
etherice 28.08.2013, 22:00
quelle

2 Antworten

3

Nach Definition von keine Verknüpfung in C ++. 11 §3.5 Programm und Verknüpfung ¶2 glaubte ich ursprünglich, dass foo<Bar> keine Verknüpfung hat, da auf sie nicht verwiesen werden kann Name nach einem anderen Bereich als dem, der den Typ Bar definiert hat (dh main() ). Dies ist jedoch nicht korrekt. Dies liegt daran, dass die Definition eines Namens mit externer Verknüpfung wie folgt beschrieben wird:

  

Wenn ein Name externe Verknüpfung hat, kann die Entität, auf die er verweist, mit Namen aus Bereichen anderer Übersetzungseinheiten oder aus anderen Bereichen derselben Übersetzungseinheit bezeichnet werden.

Und für eine Template-Funktion wird dies immer der Fall sein. Dies liegt daran, dass es einen anderen Bereich gibt, aus dem der Name abgerufen werden kann. Die Template-Funktion kann nämlich auf sich selbst verweisen. Daher hat foo<Bar> eine externe Verknüpfung. zneaks Antwort, EDIT 2 , hat einen E-Mail-Thread mit den Clang-Entwicklern, der bestätigt, dass foo<Bar> eine externe Verknüpfung haben sollte.

Also, von C ++. 11 §14.3.2 Vorlage nicht-type arguments ¶1:

  

Ein Template-Argument für einen Nicht-Template- Template-Parameter muss einer der folgenden sein: ...   

  • ein konstanter Ausdruck (5.19), der die Adresse eines Objekts mit statischer Speicherdauer und externer oder interner Verknüpfung oder eine Funktion mit externer oder interner Verknüpfung bezeichnet, einschließlich Funktionsvorlagen und Funktion Vorlagen-IDs aber ausgenommen nicht statische Klassenmitglieder, ausgedrückt (ohne Klammern) als & ID-Ausdruck , außer dass & weggelassen werden kann, wenn der Name auf eine Funktion oder ein Array verweist und ausgelassen werden soll wenn der entsprechende Template-Parameter eine Referenz ist; ...
  • Das relevanteste Geschoss ist das dritte Geschoss. Da foo<bar> eine externe Verknüpfung hat, sollte es als nicht-type Template-Parameter übergeben werden.

        
    jxh 28.08.2013, 23:04
    quelle
    3

    Ich bin zu spät zur Party, aber der Standard sagt, dass Typ-lokale Funktionen keine Verknüpfung haben (§3.5: 8):

      

    Namen, die nicht von diesen Regeln abgedeckt sind, haben keine Verknüpfung. Darüber hinaus hat ein Name, der im Blockbereich (3.3.3) deklariert wurde, keine Verknüpfung .

    Gleiches sagt weiter:

      

    Ein Typ ohne Verknüpfung darf nicht als Typ einer Variablen oder Funktion mit externer Verknüpfung verwendet werden, außer

         
    • Die Entität hat eine C-Verknüpfung (7.5) oder
    •   
    • Die Entität wird in einem unbenannten Namespace (7.3.1) oder
    • deklariert   
    • die Entität ist nicht odr-verwendet (3.2) oder ist in derselben Übersetzungseinheit definiert.
    •   

    Und in der Tat wird Clang dies erlauben:

    %Vor%

    Und wird es ohne den anonymen Namespace ablehnen.

    EDIT 1 : Wie jxh bemerkt, werden die Namen auch in der gleichen Übersetzungseinheit definiert, daher bin ich mir nicht sicher, was ich von dieser Frage halten soll.

    EDIT 2 : Die Jungs von Clang bestätigen, dass es ein Bug ist.

        
    zneak 29.08.2013 00:32
    quelle

    Tags und Links