Problem mit template-Klasse
-
Hi!
Ich habe eine Template-Klasse, welche allerdings nur char und wchar_t zulassen darf. Wie kann ich fehlerhafte Eingaben des Nutzers abfangen?
Naja, und meine nächste Frage. Ich möchte einen konstanten Zeiger auf eine Zeichenkette zurückgeben...
const char_t* getDescription() //char_t ist ein typedef auf char bzw wchar_t { return "Description"; //Wie kann ich im Falle von wchar_t das ganze als Widechar-Zeichenkette zurückgeben? }Danke schonmal

Grüße
-
Als erstes kannst du z.B die Klasse spezialisieren und nur für diese beiden Typen implementieren. Ansonsten kannst du auch mit boost.enable_if[url] arbeiten.
Beim zweiten kannst du ein L vor die Zeichenkonste setzen.
const char_t* getDescription() //char_t ist ein typedef auf char bzw wchar_t { return L"Description"; }
-
Beim zweiten kannst du ein L vor die Zeichenkonste setzen.Was darin resultieren wird, dass der Compiler jammert wenn char_t ein char ist

Im Prinzip möchte ich so ein Verhalten (Pseudocode, ich möchte das vom Compiler aufgelöst haben) :
const char_t* getDescription() //char_t ist ein typedef auf char bzw wchar_t { if(char_t == char) return "Description"; else if(char_t == wchar_t) return L"Description"; }.... enable_if werde ich mir mal ansehen, danke.
Grüße
-
Das wäre eine Möglichkeit:
template <typename CharType> class DescriptionImpl; template <> class DescriptionImpl<char> { public: const char* getDescription() const { return "Description"; } }; template <> class DescriptionImpl<wchar_t> { public: const wchar_t* getDescription() const { return L"Description"; } }; template <typename CharType> class MyClass : public DescriptionImpl<CharType> { };Ansonsten dürfte
BOOST_STATIC_ASSERTvielleicht etwas schönere Fehlermeldungen geben.Ist etwas mühsam, dass du hier Code duplizieren musst, aber ich sehe keinen Weg, zur Kompilierzeit Stringliterale an den Typen anzupassen.
-
const char_t* getDescription() //char_t ist ein typedef auf char bzw wchar_t { if(char_t == char) return "Description"; else if(char_t == wchar_t) return L"Description"; }Was spricht gegen genau diesen Code? Statt "==" halt ein
TypesEqual<char_t,char>::equaloder so und vor die Zeichenketten noch casts, dann steht das. Müsste "sicher" sein, verbraucht weniger Code und ist imo hübscher als solche ausgelagerten Dingsis.PS: Mit
template<typename T, typename U> struct TypesEqual { enum {equal=false}; }; template<typename T> struct TypesEqual<T,T> { enum {equal=true}; };
-
Badestrand_ schrieb:
Müsste "sicher" sein, verbraucht weniger Code und ist imo hübscher als solche ausgelagerten Dingsis.
Jetzt interessiert mich aber, wie deine
getDescriptionaussieht. Du kannst nämlich nicht beidereturn-Statements im Code haben, auch wenn eines davon mit Sicherheit nie erreicht wird.
-
template<typename char_t> struct X { const char_t* getDescription() { if ( TypesEqual<char_t,char>::equal ) return reinterpret_cast<char_t*>( "Description" ); else if ( TypesEqual<char_t,wchar_t>::equal ) return reinterpret_cast<char_t*>( L"Description" ); } };
-
Okay, aber ob
reinterpret_castso viel schöner ist... Edit: Ah, die Casts habe ich in deinem ersten Post überlesen und erst jetzt gesehen. Sorry für die sinnlose Frage, wie du das implementieren würdest.Abgesehen davon finde ich es unnötig, Performance für ein
ifzu verschwenden, wenn die Bedingung zur Kompilierzeit bekannt ist.
-
Nexus schrieb:
Okay, aber ob
reinterpret_castso viel schöner ist...7 statt 20 Zeilen Code und einmal Vererbung weniger, ich finde das schon ein Argument...
Nexus schrieb:
Abgesehen davon finde ich es unnötig, Performance für ein
ifzu verschwenden, wenn die Bedingung zur Kompilierzeit bekannt ist.Also mich würde es wirklich wundern, wenn das nicht rausoptimiert wird

-
Hm, stimmt eigentlich schon.

Naja, ist wohl etwas Geschmackssache. Wenn ich den Code anschauen würde, wäre mir sicher nicht sofort klar, warum ein Cast verwendet wurde. Aber ein Kommentar könnte da sicher helfen.
Vielleicht schaue ich solche Templatemetaprogrammierungs-Techniken auch etwas zu konservativ an.

-
Auf Jedenfall ist Badestrand-Lösung sehr teuer. Obwohl er Template benutzt :s Eigentlich frag ich mich, wieso in C++ String kein typedef auf basic_string<char> oder basic_string<wchar_t> jenachdem ob UNICODE definiert ist. Sowie mit entsprechend T Macro, der den Stringliteral entsprechend ersetzt.
-
Zeus schrieb:
Auf Jedenfall ist Badestrand-Lösung sehr teuer.
Ja, leider schon. Ich würde schätzen, dass man schon so mit 2 bis 3 Sekunden Delay (Ausführungszeit) rechnen muss, auf aktuellen PCs. Gerade die if-Schleife und das teure reinterpret_cast, was ja bekanntlich zur Compilezeit wirkt, düften ziemlich viel fressen. Vielleicht kannst du mal ein wenig benchmarken, dann wissen wir mehr!
-
Du meinst zu Laufzeit.
-
Zeus schrieb:
Du meinst zu Laufzeit.
Nein, er meint schon zur Compilezeit. Um Speicherbereiche anders zu interpretieren, braucht es keinen dynamischen Code.
Und er meinte sicher auch If-Abfrage. :p
-
Unglaublich teuer *g*
Das hat VC++ daraus gemacht:
mov eax, offset aDescription ; "Description" retnDanke dafür, die Lösung ist echt nicht schlecht.

-
Nexus schrieb:
Und er meinte sicher auch If-Abfrage. :p
Hihi, ich dachte, das fällt zwischen dem ganzen Unsinn gar nicht auf

Um das mal aufzuklären: Das
if ( TypesEqual<char_t,char>::equal )zerfällt beim "Auflösen" der Templates zuif ( true )bzwif ( false ); was schlicht und ergreifend wegoptimiert wird. Der reinterpret-cast hat genau 0 Kosten, da er nur die Typinformation verändert (zur Compilerzeit), bleibt nur dasreturn. Das brauchst du in jedem Fall, wodurch die Laufzeit irrelevant wird. Falls sie trotzdem jemand wissen will: Sie wird auf aktuellen Systemen ungefähr bei 0,0000000008 Sekunden liegen.