Wohlgeformtes Programm mit einer fehlerhaft geformten Template-Member-Funktion?

8

Im folgenden Ausschnitt bin ich verwirrt darüber, warum die Definition von Wrapper::f() const mein Programm nicht zu einem schlecht geformten 1 macht, obwohl es eine nicht-konstante Mitgliedsfunktion eines nicht veränderbaren Mitglieds aufruft Variable:

%Vor%

Demo 2

Wenn andererseits Data eine Nicht-Template-Klasse 3 ist, wird von meinem Compiler eine Diagnose ausgegeben:

%Vor%

Demo

Ich denke, die Antwort wird Ausdrücke wie "deducted context" enthalten ... aber ich kann den genauen Teil des Standards, der dieses Verhalten genau beschreibt, nicht genau bestimmen.

Gibt es einen Sprachanwalt, der mich in dieser Angelegenheit aufklärt?

Anmerkungen:
1) Aber ich erhalte einen Fehler, wenn ich versuche Wrapper<T>::f() const aufzurufen.
2) Ich habe mit -std=c++17 kompiliert, aber das ist nicht spezifisch für C ++ 17, also kein spezifisches Tag.
3) In diese Antwort , @Baum mit Augen zitiert [N4140, 14.7.1(2)] :

  

Die Spezialisierung des Members wird implizit instanziiert, wenn auf die Spezialisierung in einem Kontext verwiesen wird, der die Definition des Members erfordert

, aber hier im Kompilierungs-Snippet (# 2) void f() const { _data.f(); } schlägt fehl, obwohl seine "Spezialisierung nie in einem Kontext referenziert wird, der die Memberdefinition benötigt" .

    
YSC 15.12.2017, 09:34
quelle

1 Antwort

4

Snippet # 2 ist ill-formed .

Wie bereits in diese Antwort angegeben, ist die Vorlagendefinition von Wrapper::f wohlgeformt (es werden also keine Diagonstics ausgegeben), solange eine gültige Spezialisierung erzeugt werden kann .

§17.7 / 8 [temp.res] lautet:

  

Wenn Sie wissen, welche Namen Typnamen sind, kann die Syntax jeder Vorlage verwendet werden   überprüft werden. Das Programm ist schlecht geformt, keine Diagnose erforderlich, wenn:

     
  • Es kann keine gültige Spezialisierung für eine Vorlage oder eine Unteranweisung einer consExpr if - Anweisung innerhalb einer Vorlage generiert werden   Vorlage wird nicht instanziiert oder [...]
  •   

In keinem der beiden Codefragmente wird Wrapper<void>::f aufgrund der Regeln in §17.7 instanziiert .1 / 2 [temp.inst] :

  

Die implizite Instantiierung einer Klassenvorlagenspezialisierung verursacht   die implizite Instantiierung der Deklarationen , aber nicht der   Definitionen, [...].

(betont von mir getan)

Aber jetzt tritt §17.7 / 8 in Kraft: wenn es keine Instanziierung gibt und kann es keine generierte Spezialisierung geben für die die Template-Definition von Wrapper::f gültig ist (was bei Snippet # der Fall ist) 2, wie für jede generierte Spezialisierung Wrapper<T>::f , ein non-const Aufruf innerhalb einer const Funktion auf einem Member wäre durchgeführt), das Programm ist schlecht gebildet und die Diagnose wird ausgegeben.

Da die Diagnose jedoch nicht obligatorisch ist (siehe oben §17.7 / 8), kann der GCC das Snippet # 2 verweigern, während sowohl VS und clang kompilieren den gleichen Code fehlerfrei.

Für Snippet # 1 können Sie jedoch eine benutzerdefinierte Spezialisierung für Data angeben, wobei Data::f ist const (sagen wir Data<void>::f ). Daher ist eine gültige generierte Spezialisierung von Wrapper::f möglich, d. H.% Co_de%. Zusammenfassend ist Snippet # 1 wohlgeformt und Snippet # 2 ist ungültig; Alle Compiler arbeiten standardkonform.

    
Jodocus 15.12.2017, 11:06
quelle

Tags und Links