typename vs. T::template nochmal
-
Achso, krass. Hat es besondere Gründe, dass beim Rückgabetyp kein ADL (hoffe, ich benutze den Begriff jetzt nicht falsch) greifen darf? Fände ich intuitiver und ich sehe jetzt keinen Nachteil, der nicht auch für Parameter gelten würde.
-
"nachgelagerte return type"
trailing-return-type.
weder template noch typename sind an dieser Stelle erforderlich (aber einzeln oder zusammen zulässig), weil
outer<T>::inner ein member der current instantiation ist und damit bereits in der Templatedefinition
beim Namelookup gefunden und als Klassentemplate identifiziert werden kann.Ich kann die Standardstelle nicht genau finden. Ich denke, es ist
[temp.dep.type]/1 schrieb:
A name refers to the current instantiation if it is
— in the definition of [...]a member of a class template [...] the injected-class-name (Clause 9) of the [...] nested class,// will Test::SomeEnum
Jo, aber natürlich wird
SomeEnumnicht gefunden. Ich finde, das würde auch sehr komisch sein, wenn das tatsächlich so funktionieren würde
Dieses Beispiel ist definitv ill-formed und nicht vergleichbar

dass die Compiler "unfähig" [...] sind
Ich denke, daran liegt es nicht. Wäre das so schwer, hätte man es aus dem Standard entfernt (wie
export).
Aber der Standard definiert es ähnlich:A trailing-return-type is most useful for a type that would be more complicated to specify before the
declarator-id.(camper meint übrigens die declarator-id)
Hat es besondere Gründe, dass beim Rückgabetyp kein ADL [...] greifen darf?
Ich dachte, ADL ist nur für Funktionsaufrufe und hat hier gar nix verloren
- aber wie so oft kann ich mich ja auch irren 
When the postfix-expression in a function call is an unqualified-id, other namespaces not considered
during the usual unqualified lookup (3.4.1) may be searched [...]
-
Okay, danke für die Anmerkungen.

Hast Du dich jetzt bzgl. ADL geirrt oder nicht? Klingt für mich doch, als hättest Du damit recht gehabt. Hat hier wohl wirklich überhaupt nichts verloren.
Trotzdem erscheint es mir nach wie vor intuitiv, dass er auch im Klassenscope sucht, wenn es um den Rückgabetypen geht. Für mich gehört der einfach zur Methode dazu und die Methode gehört für mich zur Klasse. Bin ich da allein?
-
Wenn ich mich nicht irre:
ADL ist ja dafür da, dass wenn du eine Funktion mit unqualifizierten Namen aufrufst, für den Funktionsnamen auch in anderen Namensräumen in festgelegter Reihenfolge gesucht wird, oder entsprechend für Operatorfunktionen - diese Namensräume werden durch die Argumente festgelegt (argument dependent name-lookup).Der Rückgabewert wird aber bereits bei der ersten Deklaration der Funktion geparst und steht damit vor jedem Funktionsaufruf fest, bzw. bei der Instantiierung der entsprechenden Spezialisierung einer Funktion.
Edit: Du Schlingel! Hast ja die Anmerkung wegeditiert :p
-
Ja, habe ADL Mal nachgeschlagen statt doof rumzuraten und fest gestellt, dass ich mir mein Gelaber hätte sparen können.
Bleibt also nach wie vor nur meine Anmerkung:
Trotzdem erscheint es mir nach wie vor intuitiv, dass er auch im Klassenscope sucht, wenn es um den Rückgabetypen geht. Für mich gehört der einfach zur Methode dazu und die Methode gehört für mich zur Klasse. Bin ich da allein?

-
Eisflamme schrieb:
Bleibt also nach wie vor nur meine Anmerkung:
Trotzdem erscheint es mir nach wie vor intuitiv, dass er auch im Klassenscope sucht, wenn es um den Rückgabetypen geht. Für mich gehört der einfach zur Methode dazu und die Methode gehört für mich zur Klasse. Bin ich da allein?
Leider habe ich, und wahrscheinlich auch du, zu wenig Erfahrung um darüber eine vernünftige Aussage machen zu können. Ich sage mal pauschal nein, weil ich es erstens, wie camper, unübersichtlich finde. Und zweitens da ich denke dass das öfters, gerade bei Programmen die davon Gebrauch machen, zu Mehrdeutigkeit führen kann.*
*Natürlich ist das nur eine Qualifizierung nötig um alles wieder ins Lot zu bringen - aber dann haben wir dadurch auch nichts gewonnen.
-
LOL
Gerade überarbeite ich ein altes Projekt von mir - und gerade ändere ich Zehn out-of-class Memberfunktions-Definitionen zu trailing-return-types.
-
Im Allgemeinen wird eine Name unmittelbar aufgelöst, sobald er auftritt (nicht zuletzt, weil häufig erst diese Auflösung es ermöglicht, den Rest des Codes richtig zu interpretieren).
Außerhalb einer Templatedeklaration sind die Regeln recht einfach:
Sobald irgendein Name (ohne vorangestelltes :: ) auftritt, wird er unqualifiziert gesucht, und zwar in dem Scope, in dem in dem er lexikalisch auftritt.
Wird eine entsprechende Entität (oder ggf. mehrere) gefunden, muss entsprechend kontextabhängig je nach Art der Entität weiter geparst werden.
Wird der Name nicht gefunden, muss die Stelle daraufhin untersucht werden, ob es sich (syntaktisch) um einen Funktionsaufruf handelt. Ist das der Fall und erlauben es die Argumente, so ist der Funktionsname per ADL zu suchen (ADL interessiert sich grundsätzlich nur für Funktionen oder Funktionstemplates - außerdem kommt es nat. ggf. zu ADL, wenn zuvor bereits eine Funktion gefunden wurde).Innerhalb einer Templatedeklaration sind diese Regeln auch einfach:
es sind die Gleichen (außer dass ein zweiter ADL-Pass ggf. erst bei der Instantiierung vorzunehmen ist).Erfolgt eine Deklaration eines Members außerhalb der Klasse, so ist der lexikalische Scope der Deklaration (die bei Membern auch eine Definition sein muss) zu beachten, nur die Teile, die der deklarator-id folgen befinden sich im Scope der Klasse.
namespace foo { struct bar { typedef int type; type fun(); }; } typedef char type; type foo::bar::fun(); // ill-formed - type ist ::typeSowohl im Nicht-Template- als auch im Templatefall muss also im Allgemeinen ein qualifizierter Bezeichner verwendet werden, wenn diese Syntax benutzt wird.
Wesentliche Unterschiede zwischen Nicht-Templates und Templates gibt es hingegen, wenn es um qualifizierte Bezeichner oder Memberzugriffe geht, und dieser Bezeichner von einem Templateparameter abhängt.
Im Wesentlichen:
Abhängige Bezeichner sind solche, die
1. von einem Templateparameter abhängig sind,
2. nicht Member der current instantiation sind (ich traue mich nicht das zu übersetzen, ich finde auch den englischen Begriff furchtbar)
Abhängige Bezeichner benötigen jeweils die Schlüsselworte typename oder template, wenn es sich um Typen bzw. Templates handelt, es sei denn der Kontext verbietet sie ausdrücklich. Bezeichner, die von einem Templateparameter abhängen aber keine Abhängigen Bezeichner sind (also Member der current instantitiation) dürfen, wenn der Kontext es erlaubt mit typename/template versehen werden (sowohl in C++03 als auch C++11) - und das ist gut so, weil man ggf. erst 10mal hinschauen muss, um die Unterscheidung machen zu können.
Und C++11 erlaubt typename/template ausserdem noch an fast allen anderen Stellen, an denen die Syntax es hergibt, insbesondere auch ausserhalb von Templates.
-
2. nicht Member der current instantiation sind (ich traue mich nicht das zu übersetzen, ich finde auch den englischen Begriff furchtbar)
Er ist auch nicht korrekt. Die Instantiierung ist ein Prozess. Was sie meinen ist die aktuell instantiierte Spezialisierung.
-
Sone schrieb:
2. nicht Member der current instantiation sind (ich traue mich nicht das zu übersetzen, ich finde auch den englischen Begriff furchtbar)
Er ist auch nicht korrekt. Die Instantiierung ist ein Prozess. Was sie meinen ist die aktuell instantiierte Spezialisierung.
Das macht ihn furchtbar aber nicht inkorrekt.
Er wird so kursiv im Standard an dieser Stelle verwendet, was auf einen explizit definierten Begriff verweist (schließe ich mal, ich vermute das wird in einem der in 1.2 genannten Standards (2382 hab ich nicht) so vorgegeben, in 1.6 wird nur gesagt, was Kursivschrift innerhalb von grammatikalischen Spezifikationen bedeuten soll).Deine Übersetzung geht in die richtige Richtungg, ist aber auch nicht korrekt. Weil des um Bezeichner innerhalb einer Templatedefinition geht. Nicht um die Instantiierung derselben (nat. ist da eine Verbindung).