|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Kampfhund Super JLI'ler
Alter: 42 Anmeldedatum: 20.07.2002 Beiträge: 408
Medaillen: Keine
|
Verfasst am: 19.04.2006, 21:55 Titel: Mini-Templates |
|
|
compiler_error:
Das ist eine ganz hilfreiche Technik um Fehler bereits zur Kompilierzeit aufzudecken.
Mal ein Beispiel(ist vielleicht nicht super gewählt):
CPP: | template<class T,int N>
struct static_array
{
T array[N];
};
|
Jetzt kann es allerdings passieren, dass jemand für N 0 übergibt:
CPP: | static_array<int,0> array;
|
Das sollte natürlich nicht möglich sein. Um das zu verhindern kann man sich folgender Technik bedienen:
CPP: | template<bool generate_compiler_error>
struct compiler_error;
template<>
struct compiler_error<false>
{
};
|
Wie man sieht, gibt es zwei Spezialisierungen für compiler_error:
Eine für generate_compiler_error=true und eine für false. Die spezialisierung für true ist aber nicht definiert, denn der Struktur-Körper fehlt.
Wenn man also versucht, von compiler_error<true> eine Instanz anzulegen, dann meldet der compiler, dass die variable eine undefinierte Struktur verwendet. Dabei wird der Variablenname mit angegeben.
Das kann man nun so ausnutzen:
CPP: | template<class T,int N>
struct static_array
{
compiler_error<N==0> zero_as_N_is_not_allowed;
T array[N];
};
|
Wenn static_array nun mit 0 als N instantiiert wird, dann wird der Ausdruck "N==0" zur kompilierzeit zu "true" ausgewertet. Also wird compiler_error<true> instantiier, welche aber nicht definiert ist => compiler error.
Der Fehler sieht dan folgendermaßen aus:
Code: |
'zero_as_N_is_not_allowed' uses undefined struct 'compiler_error<generate_compiler_error>
|
Man kann also sofort erkennen, dass man 0 nicht als N übergeben darf.
In boost ist diese Technik als "static assert" bekannt (afaik).
is_same_type:
Es soll nicht nur verboten sein, für N 0 zu verwenden, sondern auch T soll eine beschränkung haben: T != void.
Wie aber überprüft man, ob ein template-typ gleich einem bestimmten typ ist?
Dies erreicht man wieder durch partielle Spezialisierung. Wir schreiben uns ein template, dass ermittel, ob zwei typen gleich sind:
CPP: | template<class A,class B>
struct is_same_type
{
enum { result = 0 };
}
template<class A> // spezialisierung für A=B
struct is_same_type<A,A>
{
enum { result = 1 };
}
|
Wie man sieht, hat die template-struktur zwei template-parameter. Außerdem hat es einen anonymen (nicht benannten) Aufzählungstypen. Die template-struktur hat außerdem eine Spezialisierung, und zwar für den Fall dass A und B der selbe typ ist. Auch die Spezialisierung hat einen anonymen Aufzählungstypen.
Schauen wir uns an, was passiert, wenn die template-struktur verwendet wird:
CPP: | std::cout<<is_same_type<int,float>::result<<std::endl;
|
Hier wird nicht die Spezialisierung verwendet, also hat result (der wert aus der Aufzählung) den wert 0.
CPP: | std::cout<<is_same_type<int,int>::result<<std::endl;
|
Hier wird die Spezialisierung verwendet, demnach hat result den wert 1.
Man kann nun also durch diese struktur zur kompilierzeit feststellen, ob zwei typen die selben sind. Man muss dazu einfach nur is_same_type<A,B>::result als boolsche konstante ansehen die das ergebnis darstellt.
Wir können dies nun so verwenden:
CPP: | template<class T,int N>
struct static_array
{
compiler_error<N==0> zero_as_N_is_not_allowed;
compiler_error<is_same_type<T,void>::result> void_as_T_is_not_allowed; // neu
T array[N];
};
|
Wenn T=void ist, dann wird die Spezialisierung von is_same_type instantiiert und result ist 1. Deswegen wird compiler_error<true> instantiiert, was - wie bereits gezeigt - eine compiler-fehlermeldung erzeugt. _________________ Kochen ist ein NP-schweres Optimierungsproblem. |
|
Nach oben |
|
|
GreveN JLI Master
Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 20.04.2006, 09:23 Titel: |
|
|
So mag ich das, ist irgendwie... smart!
Ist zwar anfürsich nichts Neues, aber klein, fein, nützlich... was will man mehr?
Sehr schön! |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|