Expression Templates
Expression Templates sind eine C++-Metaprogrammiertechnik und waren ursprünglich nicht im C++-Standard vorgesehen. Sie werden verwendet, um bereits zur Übersetzungszeit bestimmte Ausdrücke durch Templatecode zu ersetzen.
Todd Veldhuizen stellte diese Technik im Juni 1995 vor.<ref name="veldhuizen95" /> Sie sollte die Geschwindigkeitseinbußen durch temporäre Variablen bei Operator-Überladung vermeiden, gleichzeitig jedoch eine einfache Schreibweise beibehalten.
Im Grunde stellen Expression Templates vielmehr eine Abstraktionstechnik dar, die es ermöglicht, hinter einem einfach aussehenden Ausdruck eine komplexe Operation zu „verstecken“ (vgl. auch CRTP). Sie sollten nicht verwendet werden, um dynamisch Code zu generieren, sondern stattdessen um spezialisierte (bzw. optimierte) Berechnungsfunktionen aufzurufen.<ref name="iglberger_et_perf" /> Zum Beispiel sollte ein Expression Template für eine Matrizenmultiplikation besser einen speziellen Kernel wie dgemm oder einen OpenCL-Kernel aufrufen, der die eigentliche Berechnung durchführt.
Idee
Gerade im Bereich des wissenschaftlichen Rechnens, beispielsweise Simulationen, werden immer wiederkehrende Operationen auf Vektoren oder Matrizen angewandt. Hier wird gefordert, dass der Quelltext einerseits leicht lesbar – und somit auch wartbar – ist und andererseits maximal effizienter Code generiert wird.
Beispiel: Operationen auf Vektoren sollen in der einfachen Form x = c * x + x * y; darstellbar sein, an Stelle von VecAdd(x, VecScale(c, x), VecMul(x, y));
bzw. letztendlich
<syntaxhighlight lang="cpp">
for (size_t i = 0; i < x.size(); ++i)
x[i] = c * x[i] + x[i] * y[i];
</syntaxhighlight>
(Anmerkung: Seien x, y Vektoren (hier: std::vector<double>) und c ein Skalar (hier: double).)
Ursprünglich war die Technik der Operator-Überladung für solche Fälle gedacht. Allerdings werden hier temporäre Variablen angelegt, die später in die Zielvariable kopiert werden müssen, und es findet zusätzlich noch ein Funktionsaufruf statt, der den linearen Programmablauf unterbricht. (Dies kann teilweise durch Inlining umgangen werden, ist jedoch nicht garantiert und kreiert wiederum andere Probleme.) Gerade das Allozieren und Konstruieren der temporären Variablen ist sehr zeitaufwändig, besonders bei komplexen Datentypen.
Die Idee ist nun, eine Reihe Templates zu entwerfen, die einen einfachen Ausdruck (wie oben) durch den – meist umfangreicheren – Quelltext ersetzen, der das gewünschte Ergebnis berechnet.
Hierzu ruft man sich in Erinnerung, dass der obige Ausdruck auch als Baum dargestellt werden kann:
+ / \ * * / \ / \ c x x y
Nun benötigt man eine Wrapper-Klasse, die einen einzelnen Ausdruck (hier: ein Knoten) darstellt und die zugehörige Funktion unterlegt. Dann muss man nur noch eine Template-Klasse für die jeweilige Operation und deren Operations-Template anlegen (siehe Beispiel weiter unten).
Der Ausdruck x = c * x + x * y; wird dann sukzessive durch den Compiler mit den entsprechenden Templates ersetzt:
| Ausdruck | Wird zu … |
|---|---|
c * x |
<syntaxhighlight lang="cpp"> VecScale<double, double, vector<double>>(c, x) </syntaxhighlight> |
x * y |
<syntaxhighlight lang="cpp"> VecMul<double, vector<double>, vector<double>>(x, y) </syntaxhighlight> |
cx + xy |
<syntaxhighlight lang="cpp"> VecAdd<double, vector<double>, vector<double>>(cx, xy) </syntaxhighlight> |
(mit cx = c * x und xy = x * y)
Der vollständig ersetzte Ausdruck sieht dann so aus: <syntaxhighlight lang="cpp"> x = VecAdd<double, vector<double>, vector<double>>(
VecScale<double, double, vector<double>>(c, x),
VecMul<double, vector<double>, vector<double>>(x, y))
);
</syntaxhighlight>
bzw. in ausführlicher (korrekter) Schreibweise:
<syntaxhighlight lang="cpp"> x = Vector< VecAdd<double, vector<double>, vector<double>> >(VecAdd<double, vector<double>, vector<double>>(
Vector< double, VecScale<double, double, vector<double>> >(VecScale<double, double, vector<double>>(c, x)),
Vector< double, VecMul<double, vector<double>, vector<double>> >)(VecMul<double, vector<double>, vector<double>>(x, y))(x, y))
) </syntaxhighlight>
Als Letztes werden noch die Operator-Templates eingefügt und man erhält <syntaxhighlight lang="cpp"> for (size_t i = 0; i < x.size(); ++i)
x[i] = c * x[i] + x[i] * y[i];
</syntaxhighlight>
Vorsicht: Dies ist ein einfaches, positives Beispiel für den Einsatz von Expression Templates. Im Allgemeinen führt diese Technik des Ausschreibens von Operationen nicht zum Erfolg (siehe Abschnitt Geschwindigkeit).
Vor- und Nachteile
Vorteile
- klare Semantik, dadurch bessere Lesbarkeit und stark vereinfachte Wartbarkeit des Codes
- ermöglicht generische Programmierung
Nachteile
- keine Geschwindigkeitsverbesserung (im Vergleich zu einer handgeschriebenen, optimierten Funktion)
- Vergrößerung des Quelltextes durch Template-Strukturen
- längere Übersetzungszeit, da beim Ersetzen der Templates zusätzlicher Code eingefügt wird
Geschwindigkeit
Ihr Erfinder, Todd Veldhuizen, erfand sie ursprünglich, um performanten Code bei dennoch einfacher Schreibweise zu erhalten. Seit diesen Tagen hält sich hartnäckig der Mythos, dass Expression Templates eine Optimierungstechnik seien. Dies ist nicht der Fall.
Im Beispiel oben funktioniert das einfache Ersetzen von Ausdrücken noch gut, da es sich um einfache Operationen handelt und nur linear auf aufeinanderfolgende Speicherbereiche zugegriffen wird.
Wandelt man das obige Beispiel lediglich (naiv) für Matrizen ab, erhält man katastrophale Ausführungszeiten. Dies rührt von der elementweisen Berechnung jeder einzelnen Zelle her. Das einfache Ersetzen von Ausdrücken durch Template-Code führt also im Allgemeinen nicht zu performantem Code.
Implementierung
Wrapper Klassen-Template
<syntaxhighlight lang="cpp">
- include <vector>
using namespace std;
template< typename T, typename R = vector<T> > class Vector { private:
R r; // data representation
public:
Vector(const size_t n) : r(n) {}
Vector(const size_t n, const double initialValue) : r(n, initialValue) {}
// copy constructor
Vector(const R &other) : r(other) {}
// assignment operator: same type
T& operator=(const T &other)
{
for (size_t i = 0; i < r.size(); ++i)
r[i] = other[i];
return *this; }
// assignment operator: other type
template< typename T2, typename R2 >
Vector& operator=(const Vector<T2, R2> &other)
{
for (size_t i = 0; i < r.size(); ++i)
r[i] = other[i];
return *this; }
size_t size() const
{ return r.size(); }
T operator[](const size_t i) const
{ return r[i]; }
T& operator[](const size_t i)
{ return r[i]; }
const R& data() const
{ return r; }
R& data()
{ return r; }
}; </syntaxhighlight>
Klassen-Templates für Operationen
<syntaxhighlight lang="cpp"> // Addition template< typename T, typename Op1 , typename Op2 > class VecAdd { private:
const Op1 &op1; const Op2 &op2;
public:
VecAdd(const Op1 &a, const Op2 &b ) :
op1(a), op2(b) {}
T operator[](const size_t i) const
{ return op1[i] + op2[i]; }
size_t size() const
{ return op1.size(); }
};
// Multiplikation (elementweise) template< typename T, typename Op1 , typename Op2 > class VecMul { private:
const Op1 &op1; const Op2 &op2;
public:
VecMul(const Op1 &a, const Op2 &b ) :
op1(a), op2(b) {}
T operator[](const size_t i) const
{ return op1[i] * op2[i]; }
size_t size() const
{ return op1.size(); }
}; </syntaxhighlight>
Funktions-Template
<syntaxhighlight lang="cpp"> template< typename T, typename R1, typename R2 > Vector< T, VecAdd< T, R1, R2 > > operator+(const Vector<T, R1> &a, const Vector<T, R2> &b) {
return Vector<T, VecAdd< T, R1, R2 > >(VecAdd< T, R1, R2 >(a.data(), b.data()));
}
template< typename T, typename R1, typename R2 > Vector< T, VecMul< T, R1, R2 > > operator*(const Vector<T, R1> &a, const Vector<T, R2> &b) {
return Vector<T, VecMul< T, R1, R2 > >(VecMul< T, R1, R2 >(a.data(), b.data()));
}
</syntaxhighlight>
Beispiel <syntaxhighlight lang="cpp"> Vector<double> x(5000); Vector<double> y(5000); const double c = 1.234;
// Initialisieren der Vektoren ...
x = c * x + x * y; </syntaxhighlight>
Bibliotheken
- Boost uBLAS
- <templatestyles src="Webarchiv/styles.css" />{{#if:20110727145248
| {{#ifeq: 20110727145248 | *
| {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }} (Archivversionen)
| {{#iferror: {{#time: j. F Y|20110727145248}}
| {{#if: || }}Der Wert des Parameters {{#if: wayback | wayback | Datum }} muss ein gültiger Zeitstempel der Form YYYYMMDDHHMMSS sein!
| {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }} {{#ifeq: | [] | [ | ( }}{{#if: {{#if: | {{{archiv-bot}}} | }} | des Vorlage:Referrer }} vom {{#time: j. F Y|20110727145248}} im Internet Archive{{#if: | ; }}{{#ifeq: | [] | ] | ) }}
}}
}}
| {{#if:
| {{#iferror: {{#time: j. F Y|{{{webciteID}}}}}
| {{#switch: {{#invoke:Str|len|{{{webciteID}}}}}
| 16= {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }} {{#ifeq: | [] | [ | ( }}{{#if: {{#if: | {{{archiv-bot}}} | }} | des Vorlage:Referrer }} vom {{#time: j. F Y| 19700101000000 + {{#expr: floor {{#expr: {{#invoke:Str|sub|{{{webciteID}}}|1|10}}/86400}} }} days}} auf WebCite{{#if: | ; }}{{#ifeq: | [] | ] | ) }}
| 9 = {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }} {{#ifeq: | [] | [ | ( }}{{#if: {{#if: | {{{archiv-bot}}} | }} | des Vorlage:Referrer}} vom {{#time: j. F Y| 19700101000000 + {{#expr: floor {{#expr: {{#invoke:Str|sub|{{#invoke:Expr|base62|{{{webciteID}}}}}|1|10}}/86400}} }} days}} auf WebCite{{#if: | ; }}{{#ifeq: | [] | ] | ) }}
| #default= Der Wert des Parameters {{#if: webciteID | webciteID | ID }} muss entweder ein Zeitstempel der Form YYYYMMDDHHMMSS oder ein Schüsselwert mit 9 Zeichen oder eine 16-stellige Zahl sein!{{#if: || }}
}}
| c|{{{webciteID}}}}} {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }} ({{#if: {{#if: | {{{archiv-bot}}} | }} | des Vorlage:Referrer}} vom {{#time: j. F Y|{{{webciteID}}}}} auf WebCite{{#if: | ; }}{{#ifeq: | [] | ] | ) }}
}}
| {{#if:
| Vorlage:Webarchiv/Today
| {{#if:
| Vorlage:Webarchiv/Generisch
| {{#if: Blitz++ | {{#invoke:WLink|getEscapedTitle|Blitz++}} | {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html}} }}
}}}}}}}}{{#if:
| Vorlage:Webarchiv/archiv-bot
}}{{#invoke:TemplatePar|check
|all = url=
|opt = text= wayback= webciteID= archive-is= archive-today= archiv-url= archiv-datum= ()= archiv-bot= format= original=
|cat = Wikipedia:Vorlagenfehler/Vorlage:Webarchiv
|errNS = 0
|template = Vorlage:Webarchiv
|format = *
|preview = 1
}}{{#ifexpr: {{#if:20110727145248|1|0}}{{#if:|+1}}{{#if:|+1}}{{#if:|+1}}{{#if:|+1}} <> 1
| {{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Genau einer der Parameter 'wayback', 'webciteID', 'archive-today', 'archive-is' oder 'archiv-url' muss angegeben werden.|1}}
}}{{#if:
| {{#switch: {{#invoke:Webarchiv|getdomain|{{{archiv-url}}}}}
| web.archive.org =
{{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Im Parameter 'archiv-url' wurde URL von Internet Archive erkannt, bitte Parameter 'wayback' benutzen.|1}}
| webcitation.org =
{{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Im Parameter 'archiv-url' wurde URL von WebCite erkannt, bitte Parameter 'webciteID' benutzen.|1}}
| archive.today |archive.is |archive.ph |archive.fo |archive.li |archive.md |archive.vn =
{{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Im Parameter 'archiv-url' wurde URL von archive.today erkannt, bitte Parameter 'archive-today' benutzen.|1}}
}}{{#if:
| {{#iferror: {{#iferror:{{#invoke:Vorlage:FormatDate|Execute}}|}}
| {{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Der Wert des Parameter 'archiv-datum' ist ungültig oder hat ein ungültiges Format.|1}}
| }}
| {{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Der Pflichtparameter 'archiv-datum' wurde nicht angegeben.|1}}
}}
| {{#if:
| {{#if: || }}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Der Parameter 'archiv-datum' ist nur in Verbindung mit 'archiv-url' angebbar.|1}}
}}
}}{{#if:{{#invoke:URLutil|isHostPathResource|http://www.oonumerics.org/blitz/whatis.html}}
|| {{#if: || }}
}}{{#if: Blitz++
| {{#if: {{#invoke:WLink|isBracketedLink|Blitz++}}
| {{#if: || }}
}}
| {{#if: || }}
}}{{#switch:
|addlarchives|addlpages= {{#if: || }}{{#if: 1 |}}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: enWP-Wert im Parameter 'format'.|1}}
}}{{#ifeq: {{#invoke:Str|find|http://www.oonumerics.org/blitz/whatis.html%7Carchiv}} |-1
|| {{#ifeq: {{#invoke:Str|find|{{#invoke:Str|cropleft|http://www.oonumerics.org/blitz/whatis.html%7C4}}%7Chttp}} |-1
|| {{#switch: {{#invoke:Webarchiv|getdomain|http://www.oonumerics.org/blitz/whatis.html }}
| abendblatt.de | daserste.ndr.de | inarchive.com | webcitation.org =
| #default = {{#if: || }}{{#if: 1 |}}{{#invoke:TemplUtl|failure| Fehler bei Vorlage:Webarchiv: Archiv-URL im Parameter 'url' anstatt URL der Originalquelle. Entferne den vor der Original-URL stehenden Mementobestandteil und setze den Archivierungszeitstempel in den Parameter 'wayback', 'webciteID', 'archive.today' oder 'archive-is' ein, sofern nicht bereits befüllt.|1}}
}}
}}
}}
Siehe auch
Einzelnachweise
- S. B. Lippman: C++ Gems. Cambridge Univ. Press, Cambridge 2003, ISBN 0-13-570581-9.
- D. Vandevoorde, N. M. Josuttis: C++ Templates. Addison-Wesley, 2003, ISBN 0-201-73484-2.
<references> <ref name="veldhuizen95"> {{#if:2013-05-24|{{#iferror: {{#iferror:{{#invoke:Vorlage:FormatDate|Execute}}|}}| |}}}}{{#if:Todd Veldhuizen|Todd Veldhuizen: }}{{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C{{#if:Expression Templates|[{{#invoke:Vorlage:Internetquelle|archivURL|1={{#invoke:URLutil|getNormalized|1=https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}}}} {{#invoke:Vorlage:Internetquelle|TitelFormat|titel=Expression Templates}}]{{#if:| ({{{format}}})}}{{#if:| {{{titelerg}}}{{#invoke:Vorlage:Internetquelle|Endpunkt|titel={{{titelerg}}}}}}}}}|{{#if:http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C{{#if:{{#invoke:TemplUtl%7Cfaculty%7C1}}%7C{{#invoke:Vorlage:Internetquelle%7CTitelFormat%7Ctitel={{#invoke:WLink%7CgetEscapedTitle%7C1=Expression Templates}}}}|[{{#invoke:URLutil|getNormalized|1=http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}} {{#invoke:Vorlage:Internetquelle|TitelFormat|titel={{#invoke:WLink|getEscapedTitle|1=Expression Templates}}}}]}}{{#if:| ({{{format}}}{{#if:1informatik.uni-erlangen.de1995-06https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||1}}}}
| )
| {{#if:{{#ifeq:de|de||{{#if:|1}}}}| ;
| )}}}}}}{{#if:| {{{titelerg}}}{{#invoke:Vorlage:Internetquelle|Endpunkt|titel={{{titelerg}}}}}}}}}}}{{#if:http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C{{#if:{{#invoke:URLutil%7CisResourceURL%7C1=http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}}%7C%7C}}}}{{#if:Expression Templates|{{#if:{{#invoke:WLink|isValidLinktext|1=Expression Templates|lines=0}}||}}}}{{#if: | In: {{#invoke:Vorlage:Internetquelle|TitelFormat|titel={{{werk}}}}}}}{{#if: informatik.uni-erlangen.de| informatik.uni-erlangen.de{{#if: 1995-06https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C,%7C{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||,}}}}}}}}{{#if: 1995-06| {{#if:{{#invoke:DateTime|format|1995-06|noerror=1}}
|{{#invoke:DateTime|format|1995-06|T._Monat JJJJ}}
|{{#invoke:TemplUtl|failure|1=Fehler bei Vorlage:Internetquelle, datum=1995-06|class=Zitationswartung}} }}{{#if: https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C,%7C{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||,}}}}}}}}{{#if: | S. {{{seiten}}}{{#if: https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C,%7C{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||,}}}}}}}}{{#if: https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html{{#invoke:TemplUtl%7Cfaculty%7C1}}%7C+{{#if:1995-06informatik.uni-erlangen.de%7C{{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7Carchiviert%7Cehemals}}%7C{{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7CArchiviert%7CEhemals}}}}+{{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7Cvom%7Cim}}+Vorlage:Referrer{{#if:{{#invoke:TemplUtl|faculty|1}}| (nicht mehr online verfügbar)}}{{#if: 2013-05-24| am {{#iferror: {{#iferror:{{#invoke:Vorlage:FormatDate|Execute}}|}}|2013-05-24{{#if:2366063||(?)}}}}}}{{#if: 2013-06-07|;}}}}{{#if: 2013-06-07| {{#if:1995-06informatik.uni-erlangen.dehttps://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html{{#invoke:TemplUtl%7Cfaculty%7C1}}%7Cabgerufen%7CAbgerufen}} {{#switch: {{#invoke:Str|len| {{#invoke:DateTime|format| 2013-06-07 |ISO|noerror=1}} }}
|4=im Jahr
|7=im
|10=am
|#default={{#invoke:TemplUtl|failure|1=Fehler bei Vorlage:Internetquelle, abruf=2013-06-07|class=Zitationswartung}} }} {{#invoke:DateTime|format|2013-06-07|T._Monat JJJJ}}
| {{#invoke:TemplUtl|failure|1=Vorlage:Internetquelle | abruf=2026-MM-TT ist Pflichtparameter}} }}{{#if:{{#ifeq:de|de||{{#if:|1}}}}|{{#if:1informatik.uni-erlangen.de1995-06https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||1}}}}
| (
| {{#if: | | (}}
}}{{#ifeq:{{#if:de|de|de}}|de||
{{#invoke:Multilingual|format|{{{sprache}}}|slang=!|split=[%s,]+|shift=m|separator=, }}}}{{#if: |{{#ifeq:{{#if:de|de|de}}|de||, }}{{{kommentar}}}}})}}{{#if: 1995-06https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html{{#if: 2013-06-07 | {{#if:{{#invoke:TemplUtl|faculty|}}||1}} }}|{{#if: |: {{
#if:
| „{{
#ifeq: {{#if:{{#if: {{#invoke:templutl|faculty|}}|de-ch|de}}|{{#if: {{#invoke:templutl|faculty|}}|de-ch|de}}|de}} | de
| Vorlage:Str trim
| {{#invoke:Vorlage:lang|flat}}
}}“
| {{#ifeq: {{#if:{{#if: {{#invoke:templutl|faculty|}}|de-ch|de}}|{{#if: {{#invoke:templutl|faculty|}}|de-ch|de}}|de}} | de
| „Vorlage:Str trim“
| {{#invoke:Text|quote
|1={{#if:
| {{#invoke:Vorlage:lang|flat}}
| {{#invoke:Vorlage:lang|flat}} }}
|2={{#if: {{#invoke:TemplUtl|faculty|}}|de-CH|de}}
|3=1}} }}
}}{{#if:
| (<templatestyles src="Person/styles.css" />{{#if: | : }}{{#if: | , deutsch: „“ }})
| {{#if:
| ({{#if: | , deutsch: „“ }})
| {{#if: | (deutsch: „“) }}
}}
}}{{#if: {{{zitat}}}
| {{#if:
| {{#if: {{{zitat}}}
| Vorlage:": Text= und 1= gleichzeitig, bzw. Pipe zu viel }} }}
| Vorlage:": Text= fehlt }}{{#if: | {{#if: {{#invoke:Text|unstrip|{{{ref}}}}}
| Vorlage:": Ungültiger Wert: ref=
| {{{ref}}} }}
}}|.{{#if:{{#invoke:TemplUtl|faculty|1}}|{{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7C%7C{{#ifeq: 1 | JaKeinHinweis |{{#switch:
|0|=Vorlage:Toter Link/Core{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if: | [1] }} (Seite {{#switch:|no|0|=|dauerhaft }}nicht mehr abrufbar{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}. Suche im Internet Archive ){{#if: | {{#if: deadurlausgeblendet | | Vorlage:Toter Link/archivebot }} }} | (Seite {{#switch:|no|0|=|#default=dauerhaft }}nicht mehr abrufbar{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}.) }}{{#switch: |no|0|= |#default={{#if: || }} }}{{#invoke:TemplatePar|check |opt = inline= url= text= datum= date= archivebot= bot= botlauf= fix-attempted= checked= |cat = Wikipedia:Vorlagenfehler/Vorlage:Toter Link |errNS = 0 |template = Vorlage:Toter Link |format = |preview = 1 }}{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if:{{#invoke:URLutil|isWebURL|http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}} || {{#if: || }} }} | {{#if: | {{#if: || }} | {{#if: || }} }} }}{{#if: | {{#if:{{#invoke:DateTime|format||F Y|noerror=1}} || {{#if: || }} }} }}{{#switch: deadurl |checked|deadurl|= |#default= {{#if: || }} }}|#default= https://wiki-de.moshellshocker.dns64.de/index.php?title=Wikipedia:Defekte_Weblinks&dwl=http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html Die nachstehende Seite ist {{#switch:|no|0|=|dauerhaft }}nicht mehr abrufbar]{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}. (Suche im Internet Archive. ) {{#if: | {{#if: deadurlausgeblendet | | Vorlage:Toter Link/archivebot }} }}Vorlage:Toter Link/Core{{#switch: |no|0|= |#default= {{#if: || }} }}{{#invoke:TemplatePar|check |all = inline= url= |opt = datum= date= archivebot= bot= botlauf= fix-attempted= checked= |cat = Wikipedia:Vorlagenfehler/Vorlage:Toter Link |errNS = 0 |template = Vorlage:Toter Link |format = |preview = 1 }}{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if:{{#invoke:URLutil|isWebURL|http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}} || {{#if: || }} }} }}{{#if: | {{#if:{{#invoke:DateTime|format||F Y|noerror=1}} || {{#if: || }} }} }}{{#switch: deadurl |checked|deadurl|= |#default= {{#if: || }} }}[http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html }}|{{#switch: |0|=Vorlage:Toter Link/Core{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if: | [2] }} (Seite {{#switch:|no|0|=|dauerhaft }}nicht mehr abrufbar{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}. Suche im Internet Archive ){{#if: | {{#if: | | Vorlage:Toter Link/archivebot }} }} | (Seite {{#switch:|no|0|=|#default=dauerhaft }}nicht mehr abrufbar{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}.) }}{{#switch: |no|0|= |#default={{#if: || }} }}{{#invoke:TemplatePar|check |opt = inline= url= text= datum= date= archivebot= bot= botlauf= fix-attempted= checked= |cat = Wikipedia:Vorlagenfehler/Vorlage:Toter Link |errNS = 0 |template = Vorlage:Toter Link |format = |preview = 1 }}{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if:{{#invoke:URLutil|isWebURL|http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}} || {{#if: || }} }} | {{#if: | {{#if: || }} | {{#if: || }} }} }}{{#if: | {{#if:{{#invoke:DateTime|format||F Y|noerror=1}} || {{#if: || }} }} }}{{#switch: |checked|deadurl|= |#default= {{#if: || }} }}|#default= https://wiki-de.moshellshocker.dns64.de/index.php?title=Wikipedia:Defekte_Weblinks&dwl=http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html Die nachstehende Seite ist {{#switch:|no|0|=|dauerhaft }}nicht mehr abrufbar]{{#if: | , festgestellt im {{#invoke:DateTime|format||F Y}} }}. (Suche im Internet Archive. ) {{#if: | {{#if: | | Vorlage:Toter Link/archivebot }} }}Vorlage:Toter Link/Core{{#switch: |no|0|= |#default= {{#if: || }} }}{{#invoke:TemplatePar|check |all = inline= url= |opt = datum= date= archivebot= bot= botlauf= fix-attempted= checked= |cat = Wikipedia:Vorlagenfehler/Vorlage:Toter Link |errNS = 0 |template = Vorlage:Toter Link |format = |preview = 1 }}{{#if: http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html | {{#if:{{#invoke:URLutil|isWebURL|http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html}} || {{#if: || }} }} }}{{#if: | {{#if:{{#invoke:DateTime|format||F Y|noerror=1}} || {{#if: || }} }} }}{{#switch: |checked|deadurl|= |#default= {{#if: || }} }}[http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html }} }}}}}}}}}}{{#if:| {{#invoke:Vorlage:Internetquelle|archivBot|stamp={{{archiv-bot}}}|text={{#if:https://web.archive.org/web/20130524014316/http://www10.informatik.uni-erlangen.de/~pflaum/pflaum/ProSeminar/exprtmpl.html%7CVorlage:Webarchiv/archiv-bot}}
}}}}{{#invoke:TemplatePar|check |all= url= titel= |opt= autor= hrsg= format= sprache= titelerg= werk= seiten= datum= abruf= zugriff= abruf-verborgen= archiv-url= archiv-datum= archiv-bot= kommentar= zitat= AT= CH= offline= |cat= {{#ifeq: 0 | 0 | Wikipedia:Vorlagenfehler/Vorlage:Internetquelle}} |template= Vorlage:Internetquelle |format=0 |preview=1 }} </ref> <ref name="iglberger_et_perf"> {{#invoke:Vorlage:Literatur|f}} </ref> </references>
- Wikipedia:Vorlagenfehler/Vorlage:Webarchiv
- Wikipedia:Vorlagenfehler/Vorlage:Webarchiv/Archiv-URL
- Wikipedia:Vorlagenfehler/Parameter:URL
- Wikipedia:Vorlagenfehler/Parameter:Linktext
- Wikipedia:Vorlagenfehler/Vorlage:Webarchiv/Linktext fehlt
- Wikipedia:Vorlagenfehler/Parameter:Datum
- Wikipedia:Vorlagenfehler/Vorlage:"
- Wikipedia:Weblink offline fix-attempted
- Wikipedia:Vorlagenfehler/Vorlage:Toter Link
- Wikipedia:Vorlagenfehler/Vorlage:Toter Link/URL fehlt
- C++