Wenn Sie mit Typen arbeiten, die von den Vorlagenparametern innerhalb einer Vorlage abhängig sind, weiß der Compiler nicht, welche Arten von Elementen die Elemente dieses Typs sind. Sofern Sie nichts anderes angeben, wird davon ausgegangen, dass die Elemente keine Typen und keine Vorlagen sind. Aus diesem Grund versucht es, <
als ein Kleiner-als-Operator zu behandeln, aber es wird unmöglich, den Ausdruck auf diese Weise zu analysieren, wenn er >
erreicht.
Um die Fehler beseitigen Sie diese stattdessen verwenden sollten:
call_any<B>::template call<void (&)()>(f);
Dies teilt dem Compiler ausdrücklich, dass call
ist eine Schablone, also sollte es eine der <
als Anfang der Template-Parameter behandeln und nicht normaler kleiner als Operator.
Dies sollte template
als auch verwenden:
call_any<B>::call<void()>(f);
Der einzige Grund, warum Sie nicht sehen, den Fehler auf dieser Linie ist, dass es eine Möglichkeit, es als eine nicht-Vorlage zu analysieren ist:
(call_any<B>::call < void()) > (f);
Obwohl es seltsam ist, ist es syntaktisch gültig, also kommt der Compiler über diese Linie hinaus, und der erste Fehler, den Sie sehen, ist der, den Sie erwähnen. Ohne das Schlüsselwort template
würden Sie jedoch schließlich einen Fehler erhalten, sobald call_f
tatsächlich instanziiert wurde (wahrscheinlich - es gibt seltsame Wege, wie es funktionieren könnte).
Die ersten beiden Beispiele sind in Ordnung, ohne das Schlüsselwort template
zu verwenden. Da der Typ nicht von den Vorlagenparametern abhängig ist, kann festgestellt werden, dass call
eine Vorlage ist, während call_f
analysiert wird.
Sie könnten fragen: "Warum kann der Compiler nicht herausfinden, dass es eine Vorlage ist? Ich habe es als Vorlage im Code oben definiert!". Das Problem ist Spezialisierung. Sie könnten die Vorlage spezialisieren und tun etwas ganz anderes als das, was die primäre Vorlage angibt:
template<>
struct call_any<false>
{
static const int call = 5;
};
Diese Spezialisierung auch auftreten könnten nach call_f
definiert ist, so kann der Compiler nicht darauf verlassen, was die primäre Vorlage für call_any
sagt, wenn es wird analysiert call_f
.