Wie kann man überprüfen ob ein Type definiert ist?
-
Dies sollte funktionieren:
////////////////////////////////////////////////////////////////////////// // main : Implementation file #include <iostream> template<typename T, typename GW = void> struct CheckGW { static bool const RESULT = false; }; template<typename T> struct CheckGW<T, typename T::gw> { static bool const RESULT = true; }; template<bool S, typename T1, typename T2> struct Select { typedef T1 Result; }; template<typename T1, typename T2> struct Select<false, T1, T2> { typedef T2 Result; }; struct StructWithGW { typedef int gw; }; template<int I> struct Int2Type { }; void foo(Int2Type<true>) { std::cout << "true" << std::endl; } void foo(Int2Type<false>) { std::cout << "false" << std::endl; } int main() { bool const DO_SELECT = CheckGW<StructWithGW>::RESULT; foo(Select < DO_SELECT, Int2Type<true>, Int2Type<false> >::Result()); std::cin.get(); return 0; }Hab es aber nicht zu 100% geprüft. Aber denke eigentlich schon, dass es geht. Zumindest sollte es die richtige Richtung sein.
Selectund co ist ganz wichtig, damit kannst du Verzweigungen hinbekommen, ohne das ein Compilerfehler entsteht, wenn etwas vorhanden oder nicht vorhanden ist.Grüssli
-
Schönen Dank für die schnelle Antwort und in der Richtung hatte ich mir dies schon in etwa auch gedacht. Leider funktioniert bei mir der Quellcode nicht wirklich.
Es wird immer zu false evaluiert und ich kann auch leider nicht erkennen, woran dies liegt. Ich verwende eine g++-4.3.2 und habe es auch auf einem g++-4.1.2 unter linux getestet. Ich denke aber, dass es nicht am compiler liegt.
Grüße
-
Ach ich Trottle, der Code kann nicht funktionieren. Verändere die folgende Zeile, wie folgt:
bool const DO_SELECT = CheckGW<StructWithGW, int>::RESULT;Jetzt wird
DO_SELECTtrue sein. Allerdings ist es nicht das, was du willst. Zeigt dafür sehr schön meinen Denkfehler
Aktuell fällt mir nix ein, wie man es denn nun machen könnte. Ich werde mir das nochmals durch den Kopf gehen lassen, vielleicht fällt mir noch was ein. Aber aktuell muss ich zur Post

Grüssli
-
Ja, genau. So hatte ich es auch hinbekommen, aber wie Du schon sagst ist es nicht ganz was ich brauchen würde. Aber trotzdem schon mal Danke. Wenn Dir oder jemand anderem noch was einfällt, wäre ich über weitere Hilfe dankbar.
Grüße
-
Ok, also diese Lösung funktioniert auf dem MSVC2008:
////////////////////////////////////////////////////////////////////////// // main : Implementation file #include <iostream> template<bool S, typename T1, typename T2> struct Select { typedef T1 Result; }; template<typename T1, typename T2> struct Select<false, T1, T2> { typedef T2 Result; }; struct StructWithGW { typedef int gw; }; template<int I> struct Int2Type { }; template<typename T> struct Type2Type { }; typedef char Small; class Big { char dummy[2]; }; template<typename T> Small check_gw(Type2Type<typename T::gw> tt = Type2Type<typename T::gw>()); template<typename T> Big check_gw(Type2Type<T> tt = Type2Type<T>()); void foo(Int2Type<true>) { std::cout << "true" << std::endl; } void foo(Int2Type<false>) { std::cout << "false" << std::endl; } int main() { bool const FIRST = sizeof(check_gw<int>()) == sizeof(Small); bool const SECOND = sizeof(check_gw<StructWithGW>()) == sizeof(Small); foo(Select < FIRST, Int2Type<true>, Int2Type<false> >::Result()); foo(Select < SECOND, Int2Type<true>, Int2Type<false> >::Result()); std::cin.get(); return 0; }Ich möchte jetzt aber keine Frage hören, wieso denn der Kompiler nun die richtige Funktion der beiden
check_gwauswählt. Denn ich habe keine Ahnung oder höchsten so einen ganz kleinen Schimmer, aber ob dies dann wirklich auch dem Standard entspricht, weiss ich nicht.Grüssli
-
Sieht nach SFINAE aus.
-
hustbaer schrieb:
Sieht nach SFINAE aus.
Jo, das ist auch mein leichter Schimmer, bzw. noch mit der Kombination um den ambiguous Call zu verhindern, denn diese Funktion:
template<typename T> Big check_gw(Type2Type<T> tt = Type2Type<T>());Sollte ja eigentlich für jeden Typen passen. Also auch für StructWithGW. Trotzdem wird die andere Funktion ausgewählt und kein Kompilerfehler im Sinne von "ambiguous Call" geworfen, da eigentlich beide
check_gwpassen würden. Deshalb bin ich grad ein wenig überrascht, dass es wirklich funktioniert
Grüssli
-
Dravere schrieb:
diese Funktion:
template<typename T> Big check_gw(Type2Type<T> tt = Type2Type<T>());Sollte ja eigentlich für jeden Typen passen. Also auch für StructWithGW. Trotzdem wird die andere Funktion ausgewählt und kein Kompilerfehler im Sinne von "ambiguous Call" geworfen, da eigentlich beide
check_gwpassen würden. Deshalb bin ich grad ein wenig überrascht, dass es wirklich funktioniert
Bei mir bricht der Compiler genau damit ab und sagt, es ist ein "ambiguous call".
Da würde ich doch dann glatt mal behaupten, dass der g++ hier wohl dichter am Standard ist. Nur leider hilft mir dies nicht.

Ich will mal versuchen die Funktion in eine Struktur zu packen. Vielleicht hilft dies.
Gruß
-
Schreib mal diese Funktion um...
template<typename T> Big check_gw(Type2Type<T> tt = Type2Type<T>());... zu:
template<typename T> Big check_gw(...);Die Ellipse hat die niedrigste Priorität, um als Treffer in Frage zu kommen. Das könnte vielleicht den "ambiguous call" lösen.
Übrigens, was willst du damit genau erreichen? Die Lösung ist ein wenig komplex, um damit was sinnvolles zu machen, habe ich zumindest das Gefühl

Vielleicht könnte man dein Problem einfacher lösen, mit anderen Mitteln
Grüssli
-
Womit lernt man derartige Templateprogrammierung? Buch?
-
oO schrieb:
Womit lernt man derartige Templateprogrammierung? Buch?
Jop.
http://www.amazon.com/Modern-Design-Programming-Patterns-Depth/dp/0201704315
-
Dies mit der Ellipse hilft leider nicht.
Was ich erreichen will? Also ich habe eine etwas komplexere Konfiguration in einer Klasse config zusammengefasst.
etwas sowas:
struct config { typedef xy<a,b,c> nl; typedef yz<nl, ...> anl; typedef ab<anl, ... > gw; };in manchen Konfigurationen habe ich nun den Type gw und muss dann entsprechenden Code für die Initialisierung etc. generieren. Dazu habe vorgehabt eine Art Configurator mit Hilfe von Template Meta Programmierung zu schreiben und dann darüber den Code zu erzeugen.
Soweit die grobe Idee dahinter.
Gruß
-
Gibt zwei Möglichkeiten, welche du sehr viel leichter anwenden könntest:
1. Gib deinemstruct configeine statische konstante Variable, welche definiert, ob etwas ausgeführt werden soll oder nicht. Diese statische Variable, kannst du dann direkt in derSelectStruktur verwenden.
2. Führe einConfigTypeTraitsein. Dort kannst du dann zum Beispiel diese Variable per Standard auffalsesetzen. Und für alle Klassen, welche doch so eintypedef ... gwhaben, spezialisierst duConfigTypeTraitsund setzt den Wert auftrue.
2.1 Oder du setzt, falls dertypedef ... gwals nicht vorhanden angenommen werden soll, dasgwauf auf einen speziellen Typen, den du danach raussuchst. Zum Beispiel einenNullType. So haben alle Klassen eintypedef ... gw, nur bei gewissen ist er ganz sichertypedef NullType gw. Diese Spezialfälle lassen sich ganz einfach ermitteln.@"Womit lernt man derartige Templateprogrammierung? Buch?"
Wie drakon schon gesagt hat, ja über Bücher und über selber ausprobieren. Wenn man sich in den Grundlagen der Templates auskennt, dann kann ich Modern C++ Design wirklich nur wärmstens empfehlen. Was der Typ einem da präsentiert, ist der absolute Hammer. Das gibt einem einen ganz neuen Blickwinkel.Grüssli
-
Also hier eine Version die geht mit...
g++ 4.3.0
g++ 3.4.5 <-- DAS hat mich überrascht
Comeau Online 4.3.10.1 (strict=on)
MSVC 8
MSVC 9...:
#include <iostream> template<bool S, typename T1, typename T2> struct Select { typedef T1 Result; }; template<typename T1, typename T2> struct Select<false, T1, T2> { typedef T2 Result; }; template<int I> struct Int2Type { }; typedef char NoType; class YesType { NoType dummy[2]; }; template<typename T> struct Type { }; struct NoHelper { NoType result; }; template<typename T> struct YesHelper { YesType result; }; NoHelper check_gw(...) { return NoHelper(); } template <typename T> YesHelper<typename T::gw> check_gw(Type<T>) { return YesHelper<typename T::gw>(); } // -------------------------- struct StructWithGW { typedef int gw; }; struct StructWithNoGW { typedef int blubb; }; void foo(Int2Type<true>) { std::cout << "has GW" << std::endl; } void foo(Int2Type<false>) { std::cout << "has no GW" << std::endl; } // -------------------------- int main() { bool const SEL_INT = sizeof(check_gw(Type<int>()).result) == sizeof(YesType); bool const SEL_STRUCT_WITH_GW = sizeof(check_gw(Type<StructWithGW>()).result) == sizeof(YesType); bool const SEL_STRUCT_WITH_NO_GW = sizeof(check_gw(Type<StructWithNoGW>()).result) == sizeof(YesType); foo(Select < SEL_INT, Int2Type<true>, Int2Type<false> >::Result()); foo(Select < SEL_STRUCT_WITH_GW, Int2Type<true>, Int2Type<false> >::Result()); foo(Select < SEL_STRUCT_WITH_NO_GW, Int2Type<true>, Int2Type<false> >::Result()); std::cin.get(); return 0; }MSVC 7.1 hab' ich nimmer drauf, und VC6 brauchen wir garnicht erst probieren (geht sicher nicht).
-
Es funktioniert und Danke euch allen.
Grüße
PS: Sorry, dass ich mich so lange nicht gemeldet habe, aber ich war eine Weile ohne Netz.