Erlaubte Template-Argumente prüfen sinnvoll?
-
Momentan habe ich in einer Klasse eine Template-Methode. Als Templateargumente sind alle Klassen welche von einer bestimmten Klasse geerbt haben, sowie void, erlaubt.
Jetzt könnte ich ja mit Hilfe von std::is_base_of usw. überprüfen, ob im Code korrekte Datentypen verwendet wurden. Ist es sinnvoll das zu tun? Oder kann man sich das sparen?
-
Wäre es nicht sinnvoller das über Polymorphie zu machen und eine Überladung für void anzubieten?
-
#include <type_traits> class Base {}; class Derive1 : public Base {}; class Derive2 : public Base {}; struct Foo { template<class T> void foo() { static_assert(std::is_base_of<Base, T>::value || std::is_same<T, void>::value, "Must be Base of Base or void"); } }; int main() { Foo f; f.foo<void>(); f.foo<Derive1>(); f.foo<Derive2>(); //f.foo<int>(); }
-
is_base_ofberücksichtigt auch private oder ambige Basisklassen.
-
Ich würde vermutlich einfach ne implizite Konvertierung reinschreiben, da meckert der Compiler dann von selbst wenn es nicht funktioniert.
(Fürvoidwird es ja vermutlich eine eigene Spezialisierung geben...?)
-
hustbaer schrieb:
Ich würde vermutlich einfach ne implizite Konvertierung reinschreiben, da meckert der Compiler dann von selbst wenn es nicht funktioniert.
Wobei die Fehlermeldung dann vermutlich weit weniger aussagekräftig ist als die Lösung mit dem static_assert
-
kkkl schrieb:
Momentan habe ich in einer Klasse eine Template-Methode. Als Templateargumente sind alle Klassen welche von einer bestimmten Klasse geerbt haben, sowie void, erlaubt.
Sicher?
kkkl schrieb:
Jetzt könnte ich ja mit Hilfe von std::is_base_of usw. überprüfen, ob im Code korrekte Datentypen verwendet wurden. Ist es sinnvoll das zu tun? Oder kann man sich das sparen?
Meistens kann man sich es sparen. Der Verwender hat schon ein gar mulmiges Gefühl, wenn er entgegen Deiner Doku irgendwas anderes reinsteckt. Wenns dann zum Fehler kommt, muss er nicht lange nachdenken oder suchen.
Meinstens2 ist der Wunsch nach Verebungseinschränkung einer javaesken Denke geschuldet und gar nicht sinnig: Wenns mit ner anderen Klasse auch duchcompiliert, darf sie bitte auch mitspielen. Dabei denke ich an STL-Algos und so nen Schmonz, die klappen wunderbar.
Was ist das für ein Code, der mit falschen Klassen duchcompiliert, und dann auch noch was falsches macht?
class Bee{ int sum(){ string myMelody=getFromDatabase... if(myMelody) return -1;//thinking in C clog<<myMelody; return 0; }class Histogram{ int sum(){ for(... s+=*i; return s;//wellbrainedDenke nicht, daß es der Mühe wert ist, den Benutzer dagegen zu schützen. Zumal es Leute wie mich gibt, die lieber mal in den Quellcode schauen als in die Doku und dort dann von Template-Metaprogrammierung regelmäßig im Lesefluss gebremst werden.
Ich warte mal auf die concepts oder wie es im nächsten/übernächsten C++-Standard perfekt gelöst wird.
-
TNA schrieb:
hustbaer schrieb:
Ich würde vermutlich einfach ne implizite Konvertierung reinschreiben, da meckert der Compiler dann von selbst wenn es nicht funktioniert.
Wobei die Fehlermeldung dann vermutlich weit weniger aussagekräftig ist als die Lösung mit dem static_assert
Ja, möglich.
Wobei für mich viel wichtiger ist dass es verständlich ist, wenn man zu der Zeile springt die in der Fehlermeldung erwähnt wird. (Also dass die Meldung selbst kryptisch finde ich nicht so schlimm, wenn ich dann im Code sofort sehe was das Problem ist.)
Sowas wie... Foo* foo = &bar; // bar must be derived from Foo foo->DoFooStuff(); ...sollte IMO reichen.
BTW: Gibt's nen "is assignable from" oder "is implicitly convertible to" trait?
Dann könnte man das selbe auch alsstatic_assertschreiben.
Ich fände das nämlich sogar besser mitstatic_assert. Nur würde ich mir keinen Aufwand dafür antun nur um es mitstatic_assertschreiben zu können, wenn es eine sehr einfache und vor allem garantiert "richtige" Version ohnestatic_assertgibt, die auch zumindest brauchbare compile-time Fehlermeldungen erzeugt.BTW2: Ich hatte selbst schon öfter den Fall dass ich "explizit implizit" konvertieren wollte. Also genau das was
U u = t;macht. Also explizit hinschreiben dass ich nen U brauche, dabei aber eben nur implizite Konvertierungen erlauben. Gibt's da ne verständliche "inline" Schreibweise? Also eine die ohne zusätzliche Variable auskommt? Vielleicht eine Hilfsfunktion in der Boost oder sowas? Wäre ja relativ einfach...template <class T, class U> T implicit_cast(U&& u) { return u; }