Ich habe folgenden Code:
template <typename TC>
class C
{
struct S
{
template <typename TS>
void fun() const
{}
};
void f(const S& s)
{
s.fun<int>();
}
};
// Dummy main function
int main()
{
return 0;
}
Beim Erstellen mit gcc 9.2 und clang (9.0) wird ein Kompilierungsfehler angezeigt, da das template
Schlüsselwort zum Aufrufen erforderlich ist fun
. Clang zeigt:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
Ich verstehe nicht, warum der Compiler fun
im Kontext von denkt, dass es sich um einen abhängigen Namen handelt f
, da f
es sich nicht um eine Vorlage selbst handelt. Wenn ich C
zu einer regulären Klasse anstelle einer Vorlage wechsle , verschwindet der Fehler. Ich verstehe jedoch nicht, warum es überhaupt einen Fehler geben sollte, da weder S
noch f
abhängig davon TC
.
Seltsamerweise kompiliert MSVC 19.22 dies ganz gut.
Hinweis
Bevor ich abstimme, um als Betrüger von Wo und Warum zu schließen, muss ich die Schlüsselwörter "Vorlage" und "Typname" eingeben? Bitte beachten Sie, dass dies ein Sonderfall ist, in dem selbst wenn S
es sich tatsächlich um einen abhängigen Namen handelt, dieser im Kontext f
nicht abhängig wäre, wenn sie nicht Mitglieder der aktuellen Instanziierung wären.
Antworten:
Bedenken Sie :
s.a<0>(i)
enthält zwei Vergleichsoperationen wird als Ausdruck analysiert<
und>
, und dies ist gut für # 1 , aber nicht für die # 2.Wenn dies geändert wird ,
s.template a<0>(i)
ist # 2 OK und # 1 schlägt fehl. Daher ist dastemplate
Schlüsselwort hier niemals redundant.MSVC kann den Ausdruck
s.a<0>(i)
innerhalb desselben Programms in beide Richtungen interpretieren . Dies ist jedoch nach dem Standard nicht korrekt; Jeder Ausdruck sollte nur eine Analyse enthalten, mit der der Compiler umgehen kann.quelle
C
oder die andere Spezialisierung verwenden , aber niemals beide instanziieren können. Dastemplate
Schlüsselwort hier ist meiner Meinung nach immer noch nicht erforderlich, da es davonS
abhängt, welchesC
Sie instanziieren, welches ausgewählt wird. Ohne dastemplate
Schlüsselwort könnten Sie beide instanziieren, und das Verhalten von f würde für jede Instanz unterschiedlich sein.<
in einer Vorlageninstanziierung ein Vergleichsoperator und in einer anderen Instanziierung eine Öffnungswinkelklammer ist. Dies soll sicherstellen, dass Compiler Vorlagen in einem AST analysieren können (mit Platzhaltern für Vorlagentypen).fun
kann eine Vorlagenfunktion sein oder nicht (oder überhaupt nicht vorhanden sein), abhängig vom Vorlagenparameter vonclass C
.Das liegt daran, dass Sie sich spezialisieren können
S
(ohne sich zu spezialisierenC
):Da der Compiler
fun
beim ersten Betrachtenclass C
(vor dem Ersetzen des Vorlagenparameters) wissen möchte, ob es sich um eine Vorlage handelt oder nicht ,template
ist dies erforderlich.quelle
S
jemals zugegriffen werden kannf
. Wenn dies nicht möglich ist, macht es keinen Sinn, diese Einschränkung zu haben, daf
sie sowieso nicht angezeigt werden können.f
es.