Welcher Teil der C ++ - Spezifikation verhindert, dass die argumentabhängige Suche nach Funktionsvorlagen in den zugehörigen Namespaces sucht? Mit anderen Worten, warum kann der letzte Aufruf main
unten nicht kompiliert werden?
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
void non_template(foo const&) {}
}
int main() {
ns::foo f;
non_template(f); // This is fine.
frob<0>(f); // This is not.
}
using namespace ns;
oder diens::
Kompilierung besteht die Kompilierung. Das ist eine gute Frage.Antworten:
Dieser Teil erklärt es:
C ++ Standard 03 14.8.1.6 :
quelle
f<3>(b)
ist ein Argument Funktionsaufruf , bis er entschieden hat , dass<3>
eine Liste Template - Arguments ist umgekehrt wir. Ich kann nicht entscheiden, ob<3>
es sich um eine Vorlagenargumentliste handelt, bis wir festgestellt habenf()
, dass es sich um eine Vorlage handelt. Da dieses Henne-Ei-Problem nicht gelöst werden kann, wird der Ausdruck als analysiert(f<3)>(b)
, was keinen Sinn ergibt . " Beachten Sie, dass dies dertemplate
Disambiguierungssyntax für Vorlagen für Elementfunktionen ähnelt .template f<3>(b)
kann eine bessere Syntax sein?(
...)
(beachten Sie das Fehlen eines Operators vor der Klammer) ist jedoch immer ein Funktionsaufruf, und der Compiler weiß das, sobald er die geöffnete Klammer sieht. Das Problem hierbei ist, dass<
dies sowohl als Operator als auch als Anfang einer Vorlagenargumentliste dienen kann und der Compiler eine Menge zusätzlicher Analysen durchführen muss, um herauszufinden, welche (und möglicherweise gibt es einige Codeanordnungen, bei denen dies nicht möglich ist eindeutig zu tun). Es scheint, dass die Standardautoren beschlossen haben, dies illegal zu machen, vielleicht um die Haare der Compiler-Entwickler zu retten.Seit c ++ 20 funktioniert adl auch mit expliziten Funktionsvorlagen. Hier ist der Vorschlag: P0846R0 : ADL- und Funktionsvorlagen, die nicht sichtbar sind :
Derzeit hat nur GCC 9 diese Funktion implementiert, sodass Ihr Beispiel kompiliert werden kann.
live demo
.quelle
Ich möchte die leicht akzeptierte Antwort verfeinern. Es ist in der OP-Frage nicht klar, aber der wichtige Teil des Standards (zitiert von Kornel) ist folgender (Schwerpunkt Mine):
Was also verboten ist, ist sich auf ADL zu verlassen und explizite Vorlagenargumente zu verwenden. Leider erfordert die Verwendung von Vorlagenargumenten, die nicht vom Typ sind, die Verwendung expliziter Argumente (es sei denn, sie haben Standardwerte).
Unten finden Sie einen Beispielcode, der dies zeigt:
[Leben]
quelle
Edit: Nein, das ist nicht richtig. Siehe @ Kornels Antwort .
Ich bin nicht ganz sicher , aber Stroustrup „The C ++ Programmiersprache“ Ich denke , dass 13.8.4 Anhang C Abschnitt Konsultation könnte die Ursache sein.
Da
frob
es sich um eine Vorlage handelt, kann man sie möglicherweisei=0
zu einem Zeitpunkt spezialisieren, nachdem Sie sie aufgerufen haben. Dies bedeutet, dass der Implementierung zwei Möglichkeiten zur Auswahl übrig bleiben, welchefrob
aufgerufen werden soll, wie es scheint. Sie kann sie zum Zeitpunkt der Instanziierung oder am Ende der Verarbeitung der Übersetzungseinheit auswählen .Ich denke, das Problem ist, dass Sie es tun könnten
quelle