AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Generics <> Templates ?

Ein Thema von Ghostwalker · begonnen am 29. Jun 2007 · letzter Beitrag vom 29. Jun 2007
Antwort Antwort
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#1

Generics <> Templates ?

  Alt 29. Jun 2007, 11:18
In letzter Zeit stößt man ja öfter auf den Begriff Generics, weshalb ich mich mal versucht habe schlau zu machen. Aber irgendwie wird mir der Unterschied zwischen Generics und Templates (c++-Templates) nicht wirklich klar. Für mich hört sich das an wie zwei Begriffe für die ein und die selbe Sache

Man baut sich eine abstrakte Vorlage, die später (z.B. durch einen Prä-Prozessor) typisiert wird.


Vielleicht kann mir hier mal jemand auf die Sprünge helfen
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#2

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 11:55
Zitat von Ghostwalker:
Man baut sich eine abstrakte Vorlage, die später (z.B. durch einen Prä-Prozessor) typisiert wird.
Das wären Templates. Generics sind vorkompilierte Klassen, die Jitter oder Slots enthalten, die dann mit Methodenzeigern/Infos der Spezialisierung überschrieben werden.
Vorteil ist, dass du einen Generic direkt kompilieren kannst und somit schon ohne Spezialiserung Fehlermeldungen bekommst.
Nachteil ist, dass du keine Operatoren benutzen kannst. Und auch sonst kannst du nur die Dinge benutzen, die du durch Einschränkungen der Typenparameter festgelegt hast.

Hier mal ein Bleistift (ist allerdings in Chrome, da Delphi noch keine Generics hat):
Delphi-Quellcode:
type
  IDoSomething = public interface
    method DoSomething : String;
  end;


  GenericSample<T> = public static class
    where T is IDoSomething;
  public
    class method Test(instance : T);
  end;

implementation

class method GenericSample<T>.Test(instance : T);
begin
  var miep := instance.DoSomething();
  Console.WriteLine(miep);
end;
Wie du siehst, kann ich die Methode benutzen, weil ich T so eingeschränkt habe, dass es IDoSomething implementieren muss.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#3

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 12:57
Templates sind statisch polymorph, sämtlicher typenspezifischer Code wird also zur Übersetzungszeit generiert. Das führt z.B. bei extensiver Verwendung von Template-Klassen wie der STL zu einem nicht unbeträchtlichen Code-Bloat, da sämtlicher Code für jede Typkombination, mit der das Template instantiiert wird, neu generiert wird.
Da der Code zur Compilierzeit an die Typen angepaßt werden muß, muß er dem Compiler auch zur Verfügung stehen; daher ist es nötig, die gesamte Implementation eines Templates in Headerdateien unterzubringen. (Es gibt dafür zwar das Schlüsselwort export, doch implementiert das praktisch kein Compiler.) Dies ist bei Generics nicht der Fall, da sie zur Laufzeit typisiert werden.

Generics sind allerdings derzeit dadurch im Vorteil, daß man die benötigte Schnittstelle angeben und dadurch undurchschaubaren Fehlermeldungen vorbeugen kann; das wird aber in C++0x mit Concepts auch möglich sein.

Und natürlich gibt es für Generics keine Wertparameter. Damit fällt ein Großteil der Möglichkeiten der Template-Metaprogrammierung weg, durch die in C++ ganz verrückte Dinge möglich werden, z.B. die Wahl eines Typs abhängig davon, ob zwei andere Typen gleich sind:
Code:
typedef IfThenElseType <TypesAreEqual <T, const T>::result,
    RandomIterator <const T, Base, direction, iter>,
    _some_struct_t>::type
        const_iterator_type;
Moritz
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#4

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 15:17
Ich halte mal fest (hoffentlich hab ich das richtig verstanden):

Templates:

Untypisierte Vorlagen, die vor der Compilierung durch einen Prä-Prozessor typisiert werden,
so das der Compiler zu jeder typisierten Variante entsprechenden Code hat und compilieren kann.

Generics:

Untypisierte "Vorlage", die der Compiler compilieren kann. Diese werden aber erst zur Laufzeit
entsprechend typisiert werden. Was aber auch bedeutet, das eine Typprüfung erst zur Laufzeit
stattfinden kann, da erst da der Typ bekannt ist.


Ist das so richtig ?

@Elvis

Ähm..also...das Beispiel....naja...das könnte man auch heute schon ohne Generics implementieren
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 15:57
Zitat von Ghostwalker:
Generics:

Untypisierte "Vorlage", die der Compiler compilieren kann. Diese werden aber erst zur Laufzeit
entsprechend typisiert werden. Was aber auch bedeutet, das eine Typprüfung erst zur Laufzeit
stattfinden kann, da erst da der Typ bekannt ist.


Ist das so richtig ?
Die Typprüfung findet bereits zur Compilezeit statt, allerdings dort wo dein instantiierter Typ deklariert wird - dort kannst du für <T> nämlich nur einen passenden Typen einsetzen.

Ein schönes Beispiel dafür sind typisierte Listen:
Delphi-Quellcode:
type
  TGenericList<T> = class
    where T is TObject
  private
    function GetItem(Index: Integer): T;
    procedure SetItem(Index: Integer; const Value: T);
  public
    procedure Add(AValue: T);
    property Items[Index: Integer]: T read GetItem write SetItem;
  end;
Diese Klasse wir fertig übersetzt in Maschinensprache genau so aussehen wie TObjectList - die Elemente sind TObjects. Sie hat jedoch den Vorteil, dass man Eigenschaften wie "Items" und Methoden wie "Add" wirklich typisieren kann.

Wenn du allerdings einen Typen davon ableitest mit (ich kenne mich mit der Chrome-Syntax nicht aus, kann also falsch sein)
Delphi-Quellcode:
var
  WinControlList = TGenericList<TWinControl>;
dann kann der Compiler schon prüfen, dass nur TWinControl-Objekte darin abgelegt werden. Dann sieht es so aus als ob du den Typ deklariert hättest mit <TWinControl> statt <T>:
Delphi-Quellcode:
type
  // Geht so natürlich nicht
  TGenericList<TWinControl> = class
  private
    function GetItem(Index: Integer): TWinControl;
    procedure SetItem(Index: Integer; const Value: TWinControl);
  public
    procedure Add(AValue: TWinControl);
    property Items[Index: Integer]: TWinControl read GetItem write SetItem;
  end;
... und der Compiler kann dann beim Übersetzen schon einen Typfehler anmeckern, wenn du irgendetwas anderes als ein TWinControl zu deiner Liste hinzufügen willst.
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#6

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 17:20
Aaaaah.....jetzt wirds hell

Das heißt man hat die "Funktionalität" von Templates ohne den ganzen zusätzlichen Code, den ein Prä-Prozessor verzapft, und trotzdem die gewohnte pascalsche Typsicherheit
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#7

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 17:36
Zitat:
Das heißt man hat die "Funktionalität" von Templates ohne den ganzen zusätzlichen Code, den ein Prä-Prozessor verzapft, und trotzdem die gewohnte pascalsche Typsicherheit
Das kann man grundsätzlich so sehen... Allerdings: In C++ ist nicht der Präprozessor für Templates zuständig, sondern der Compiler, und das bereits erwähnte Schlagwort TMP (Template Meta Programming) ist weit mehr als "Generics zur Kompilierzeit". Stark vereinfacht ausgedrückt ermöglicht es, Programme im Compiler auszuführen. Klassisches Beispiel:
Code:
template< int i >
class Factorial{
  public:
      enum {Value = i * Factorial<i - 1>::Value};
};

class Factorial< 1 >{
  public:
      enum {Value = 1};
};
Das ist eine Klasse Factorial, die zur Kompilierzeit (!) eine Fakultät berechnet. Wird ungefähr so verwendet:
Code:
int n = Factorial<10>::Value;
Ob man das braucht, ist eine andere Frage, aber das ist etwas, das man mit Generics allgemein nicht machen kann.
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#8

Re: Generics <> Templates ?

  Alt 29. Jun 2007, 18:56
Zitat von Ghostwalker:
Das heißt man hat die "Funktionalität" von Templates ohne den ganzen zusätzlichen Code, den ein Prä-Prozessor verzapft, und trotzdem die gewohnte pascalsche Typsicherheit
Ungefähr so. Dafür hast du einen gewissen Overhead zur Laufzeit.

Der Code-Bloat läßt sich auch bei Templates vermeiden, indem man Templates intern über typagnostische Klassen implementiert. Leider ist das für die STL nicht so einfach, da diese laut Standard (auch bezüglich der Allokatoren) eine gewaltige Flexibilität bieten muß.


Zitat von OregonGhost:
Ob man das braucht, ist eine andere Frage
Zumindest ist es sehr nützlich. Vielleicht nicht gerade für numerische Berechnungen, aber ein praktisches Beispiel hatte ich weiter oben gepostet. Hier etwas ausführlicher:
Code:
template <typename T,
          typename Base,
          int direction = UCL_ITERWRAP_FORWARD,
          typename iter = T*,
          typename tag = std::bidirectional_iterator_tag> // only for derived classes
    class BiDiIterator
        : public std::iterator <tag, T>
{
    typedef std::iterator <tag, T> _iterBase;
private:
    struct _some_struct_t {};
public:
    typedef typename IfThenElseType <TypesAreEqual <T, const T>::result,
        BiDiIterator <const T, Base, direction, iter>,
        _some_struct_t>::type
            const_iterator_type;
    typedef BiDiIterator iterator_type;
    ...
public:
    BiDiIterator (const iterator_type& rhs) : _ptr (rhs._ptr) {}
    BiDiIterator (const const_iterator_type& rhs) : _ptr (rhs._getWrappedIterator ()) {}
   ...
};
Das stammt aus meiner Implementation eines Iterator-Wrappers, der, abhängig davon, ob value_type bereits const ist, sowohl als iterator als auch als const_iterator genutzt werden kann. Allerdings muß ein iterator sowohl aus iterator- als auch aus const_iterator-Objekten konstruierbar sein - und wenn der Iterator dann schon ein const_iterator ist, gibts den Kopierkonstruktor zweimal. Um das zu vermeiden, nimmt der zweite Konstruktor, je nachdem, ob value_type das gleiche wie const value_type ist, entweder einen const_iterator oder eine nichtöffentliche Struktur entgegen.
Weiter kann der Iterator über einen Template-Parameter entweder als (forward-)iterator oder reverse_iterator eingesetzt werden. Auch verwendet er je nachdem, ob der Iteratortyp, den er wrappt, einfach nur ein Zeiger auf den value_type (der immer vorwärts iteriert) oder ein echter reverse_iterator ist, dessen Inkrement- oder Dekrementoperator.

Mach das mal ohne TMP
Moritz
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz