Zeitpunkt der Instanziierung von Templates
-
Ich bin mir hier jetzt nicht 100% sicher und hoffe ich blamier mich nicht, aber wenn ich mich recht entsinne, und http://www.c-plusplus.net/forum/81033 mir betrachte, tut der g++ dann nicht genau das richtige?
und mit
// Benutzerfunktion, für T = UserClass template <> void UserFunction<UserClass>(UserClass c);hättest du beim Aufruf das gewünschte Ergebnis?
-
unsicherer schrieb:
Ich bin mir hier jetzt nicht 100% sicher und hoffe ich blamier mich nicht
Keine Sorge, hier scheint sich niemand wirklich sicher zu sein

Geht es im verlinkten Thread nicht eher um Templatespezialisierungen? Denn das Beispiel hier hat ja damit nichts zu tun. Überhaupt mag ich Spezialisierungen von Funktionstemplates nicht und ziehe Überladungen eigentlich immer vor.
Ich hatte früher auch immer in Erinnerung, dass zumindest von Templateparametern abhängige Ausdrücke erst bei der Instanziierung kompiliert werden (d.h. für das Lookup werden auch die dort sichtbaren Namen verwendet). Würde ja um einiges mehr Sinn machen als bei der Definition. Ich muss bei Gelegenheit mal im Standard wühlen, fürchte aber, dass das wieder in eine Interpretiererei ausarten könnte...
-
Ich hab im Hinterkopf was von "2-phase-lookup", soll heißen, dass die Namen in zwei Schritten zu unterschidelichen Zeiten nachgeschaut werden. IIRC macht das nur einer (oder garkeiner?) von beiden Compilern wirklich korrekt. Das stand vermutlich im Josuttis/Vandervoorde - hab ich aber grad nicht zur Hand, müsste zu Hause mal nachschlagen.
-
Wenn man die Reihenfolge von Template und der Ueberladung nicht mit anderen Templates mischt, dann liefert g++ auch
Tundintals Ausgabe.
-
gcc macht es richtig, msvc nicht:
14.6.2/1
...
In an expression of
the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of
the expressions in the expression-list is a type-dependent expression (14.6.2.2).In
Func(T());sind sowohl T (14.6.2.1) als auch T() (14.6.2.2) type-dependent. Damit ist auch func ein abhängiger Name.
14.6.4 Dependent name resolution [temp.dep.res]
1 In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
— Declarations from namespaces associated with the types of the function arguments both from the instantiation
context (14.6.4.1) and from the definition context.Und damit ist alles klar. Bei der Definition des Templates ist nur das Funktionstemplate sichtbar. ADL im zweiten Schritt nützt auch nichts: fundamentale Typen haben keinen assoziierten Namensraum. Würde man in dem Code hingen das int durch eine entsprechende Klasse ersetzen, würde das vom OP wohl erwartete Verhalten herauskommen.
-
Vielen Dank für die nachträgliche Erklärung!
camper schrieb:
Würde man in dem Code hingen das int durch eine entsprechende Klasse ersetzen, würde das vom OP wohl erwartete Verhalten herauskommen.
Das ist ja wieder mal super-unintuitiv. Ich frage mich, was man mit der Sonderbehandlung von fundamentalen Typen hier bezweckt. Gerade falls man
typedefs hat, kann sich bei einer Typänderung das Programmverhalten komplett ändern, ohne dass man zur Kompilierzeit was davon mitbekommt.
-
Habe gar nicht gemerkt, dass der Thread so alt ist. Der stand mitten zwischen den Anderen von heute. Komisch.
-
Kein Problem, im Gegenteil! Ich bin froh, dass das Ganze doch noch geklärt wurde

Auch wenn mir persönlich die Art, wie C++ das handhabt, nicht gefällt. Aber vielleicht übersehe ich auch die Intention hinter der "Spezialbehandlung" von fundamentalen Typen...
-
Super ... ich hatte das schon wieder ganz vergessen, dass ich das nachgucken wollte. Wie gesagt, was name lookup angeht, vertraue ich eigentlich dem GCC mehr. Die Erklärungen überraschen mich also nicht.

Danke, camper.
-
Nexus schrieb:
Aber vielleicht übersehe ich auch die Intention hinter der "Spezialbehandlung" von fundamentalen Typen...
Ich kann mir eigentlich nicht vorstellen, dass das eine gewollte Spezialbehandlung ist. Die Regeln sind doch so komplex, könnte sich sowas nicht einfach "ergeben"?
Und: Findet man solche versteckten Abstrusitäten in anderen Sprachen eigentlich auch? Oder ist das eine Kombi durch die heterogenen Compiler, das lange Regelwerk (insb. durch Templates?), den sorgsam ausformulierten Standard und das relativ hohe Niveau mancher Benutzer der Sprache?
Ich kenne mich in anderen Programmiersprachen nicht so gut aus wie in C++, aber ich versuche mir grad eine ähnliche Diskussion zu Python- oder Java-Verhalten vorzustellen.
-
Nexus schrieb:
Aber vielleicht übersehe ich auch die Intention hinter der "Spezialbehandlung" von fundamentalen Typen...
Ich sehe da eigentlich keine Sonderbehandlung. Der assozierte Namensraum einer Entität ist derjenige Namensraum, in dem diese definiert wird (bzw. bei zusammengesetzten Typen, die Menge aller assozierten Namensräume, von denen sich der Typ ableitet). Fundamentale Typen können nicht definiert werden, folglich gibt es auch keinen assozierten Namensraum für sie. Was wäre denn die Alternative? der globale Namensraum? ::std? Der (überraschende Effekt) des nicht Gefundenwerdens ist ja trotzdem nicht nur auf fundamentale Typen beschränkt
#include <iostream> #include <vector> struct Foo {}; template <typename T> void Func(T) { std::cout << "T" << std::endl; } template <typename T> void Use() { Func(T()); } void Func(int) { std::cout << "int" << std::endl; } void Func(Foo) { std::cout << "Foo" << std::endl; } template <typename T> void Func(T*) { std::cout << "T*" << std::endl; } void Func(std::vector<char>*) { std::cout << "std::vector<char>*" << std::endl; } int main() { Use<double>(); // T Use<int>(); // T Use<Foo>(); // Foo Use<Foo*>(); // T* Use<std::vector<char>>(); // T - Überladung müsste im Namensraum ::std stattfinden, was nat. nicht geht Use<std::vector<char>*>(); // T Use<std::vector<Foo>*>(); // T* }Man kann sicherlich über das Für und Wider des 2-Phasen-Lookups diskutieren. Damit kann man allerdings auch Bücher füllen

Zusammenfassend: Überladung ist fast genauso böse wie Spezialisierung.