Programiersprache für Anfänger
-
DEvent schrieb:
Fuer T kann ich ein int, float oder eben ein String einsetzen....Das ist das gleiche Verhalten wie z.B. in JavaScript.
naja, in javascript würde ein stringvergleich wahrscheinlich gehen. dieses c++template würde aber bei
GetMax("hallo","doof")
pointer vergleichen, d.h. für char* braucht man 'ne spezialversion, die 'strcmp' oder sowas benutzt. das wäre eine kleine stolperfalle für anfänger.
-
~fricky schrieb:
naja, in javascript würde ein stringvergleich wahrscheinlich gehen. dieses c++template würde aber bei
GetMax("hallo","doof")
pointer vergleichen, d.h. für char* braucht man 'ne spezialversion, die 'strcmp' oder sowas benutzt. das wäre eine kleine stolperfalle für anfänger.
Wobei man normalerweise davon ausgeht, das std::max nicht mit bekannten Werten aufgerufen wird (Sonst könnte man das ergebnis auch direkt hinschreiben). Sprich, in der Regel sieht es eher so aus (ganz davon abgesehen das strcmp C und nicht C++ ist):
std::string a = "Hallo"; // Initialisierungen stellvertretend für Codeaufrufe std::string b = "Welt"; // zwischendrin std::string ergebnis = std::max(a, b);
Und das liefert das erwartete Erebnis.
-
asc schrieb:
Und das liefert das erwartete Erebnis.
ok, aber
const char *m = std::max("hello", "world")
geht trotzdem nicht, oder täusche ich mich? macht std::max dann auch 'nen pointervergleich?
-
DEvent schrieb:
Ich habe auch nichts anderes behauptet. Fuer T kann ich ein int, float oder eben ein String einsetzen. Der Compiler ueberprueft den Typen nicht, sondern nur das Interface. Wenn mein eingesetzter Type eben den operator< nicht implementiert, also das Interface nicht stimmt, dann gibt es ein Fehler. Das ist das gleiche Verhalten wie z.B. in JavaScript.
Sorry, kenne JavaScript leider nicht. Kann dazu also nichts sagen. Aber bei C++ ist es ein gutes und gewolltes Verhalten, das ich einen Compiler-Error erhalte. Also weiß ich jetzt auch nicht, was dich wirklich daran stört, wenn du sagst "wie in JavaScript".
-
~fricky schrieb:
asc schrieb:
Und das liefert das erwartete Erebnis.
ok, aber
const char *m = std::max("hello", "world")
geht trotzdem nicht, oder täusche ich mich? macht std::max dann auch 'nen pointervergleich?
Das wird so nicht funktionieren, da er ja kein const char* zurück liefert, sondern entsprechend dem impliziten Template-Parameter ein const char[6].
Hem...
-
HansiHinterseher schrieb:
~fricky schrieb:
asc schrieb:
Und das liefert das erwartete Erebnis.
ok, aber
const char *m = std::max("hello", "world")
geht trotzdem nicht, oder täusche ich mich? macht std::max dann auch 'nen pointervergleich?
Das wird so nicht funktionieren, da er ja kein const char* zurück liefert, sondern entsprechend dem impliziten Template-Parameter ein const char[6].
dann braucht's wohl doch eine selbstgestrickte variante, wie etwa das:
template <> const char* max(const char* a, const char* b) { return strcmp(a, b) > 0 ? a : b ; }
^^ausserdem noch in den std-namespace verfrachten.
-
HansiHinterseher schrieb:
~fricky schrieb:
asc schrieb:
Und das liefert das erwartete Erebnis.
ok, aber
const char *m = std::max("hello", "world")
geht trotzdem nicht, oder täusche ich mich? macht std::max dann auch 'nen pointervergleich?
Das wird so nicht funktionieren, da er ja kein const char* zurück liefert, sondern entsprechend dem impliziten Template-Parameter ein const char[6].
Hem...Klar geht das:
const char* i = std::max("aaa", "aaa");
Der Compiler liefert ja auch den Typen, wenn ich fuer i den falschen Typen einsetze:
test2.cpp:42: error: invalid conversion from 'const char*' to 'int'
Allerdings bezweilfe ich stark, dass der Code das macht, was der Programmierer damit gemeint hat.
-
DEvent schrieb:
Klar geht das:
const char* i = std::max("aaa", "aaa");
Der Compiler liefert ja auch den Typen, wenn ich fuer i den falschen Typen einsetze...
wie jetzt? der eine sagt es geht nicht, der andere sagt, es geht. also was nun?
-
Ob es geht hängt wohl vom Compiler ab. Mit MSVC 2005 geht es z.B. nicht.
-
hustbaer schrieb:
Ob es geht hängt wohl vom Compiler ab. Mit MSVC 2005 geht es z.B. nicht.
ist das nicht eher eine frage der stl-implementation? wie auch immer, c++ ist für anfänger absolut nicht geeignet. ich hoffe, darüber sind wir uns jetzt einig. ihr seht ja selbst, welch einfache dinge (im vergleich zu anderen sprachen/systemen) in c++ viele, viele fragen aufwerfen.
-
ist das nicht eher eine frage der stl-implementation?
Hm. Pfuh. Ja, das zumindest auch. Obwohl ...
Beispiel (mit MSVC 2005):
#include <iostream> // geht mit array-typen template <class T> T const& min1(T const& a, T const& b) { std::cout << "T = " << typeid(T).name() << std::endl; if (a < b) // beim vergleich zerfällt "char const (&)[2]" anscheinend zu "char const*", return a; // es werden also zeiger verglichen, nicht der array-inhalt else return b; } // geht NICHT mit array-typen template <class T> T const& min2(T const& a, T const& b) { std::cout << "T = " << typeid(T).name() << std::endl; return a < b ? a : b; // MSVC 2005 ermittelt hier als typ des ausdrucks // "bool ? char const (&)[2] : char const (&)[2]" anscheinend // einfach "char const*" - warum auch immer } // geht mit array-typen, obwohl's IMO eigentlich äquivalent zu min2 sein sollte template <class T> T const& min3(T const& a, T const& b) { std::cout << "T = " << typeid(T).name() << std::endl; return a < b ? static_cast<T const&>(a) : static_cast<T const&>(b); } template <class T> void show_type(T) { std::cout << "T = " << typeid(T).name() << std::endl; } template <class T> void show_type_cref(T const&) { std::cout << "T = " << typeid(T).name() << std::endl; } int main() { show_type("foo"); char* s = "foo"; // geht (korrekter-, wenn auch unsinnigerweise)! man beachte aber dass show_type("foo") "char const *" als Typ ausgibt! show_type_cref("foo"); typedef char const (&T)[2]; T x = min1("a", "b"); std::cout << x << std::endl; T y = min1("d", "c"); std::cout << y << std::endl; // T z = min2(a, b); // geht nicht T z = min3("e", "f"); // geht wieder?!? return 0; }
Output:
T = char const * T = char const [4] T = char const [2] b T = char const [2] c T = char const [2]
Bei einigen Dingen bin ich mir hier nicht ganz sicher...
- Welcher Typ sollte bei show_type("foo") rauskommen?
- Welcher Typ sollte bei show_type_cref("foo") rauskommen?
- Sollte ein "const-ref-auf-array" Typ bei "a < b ? a : b" wirklich zu "T const*" zerfallen??? Und darf es einen Unterschied machen ob man explizit nochmal nen Cast schreibt (min2 vs. min3)? IMO müsste sich zumindest min2 gleich wie min3 verhalten...
- Muss std::min die Parameter (und den Returnwert) per const-ref nehmen, oder wäre ein einfaches "template <class T> T min(T, T)" auch OK?
Und nochmal zu 1: IMO dürfte der Typ auf jeden Fall nicht const sein, da ein String-Literal laut Standard nicht const ist. Es ist zwar "gut" dass wenigstens hier das const "magischerweise" dazukommt, da die Regel "String Literale sind nicht const" sowieso Blödsinn ^4 ist, aber komisch ist es schon irgendwie.
Alles sehr seltsam...
wie auch immer, c++ ist für anfänger absolut nicht geeignet
ACK. Wobei hinzuzufügen ist dass Anfäger in jeder Sprache kaum ein 100% korrektes Programm hinbekommen werden, welches auch alle Spezial- und Fehlerfälle korrekt behandelt
-
hustbaer schrieb:
Und nochmal zu 1: IMO dürfte der Typ auf jeden Fall nicht const sein, da ein String-Literal laut Standard nicht const ist. Es ist zwar "gut" dass wenigstens hier das const "magischerweise" dazukommt, da die Regel "String Literale sind nicht const" sowieso Blödsinn ^4 ist,
wohl aus kompatiblitätsgründen, damit sowas wie
char *p = "hello";
funzt und damit man funktionen mit string-literalen aufrufen kann, die 'nen char* erwarten. sowas wie"hello"[1] = 'a';
wird wohl compilieren, aber trotzdem crashen (hab's nicht probiert, mangels c++ compiler hier).hustbaer schrieb:
...aber komisch ist es schon irgendwie.
Alles sehr seltsam...in der tat. da ist mal wieder dieses erstaunen: 'bin ich wirklich der erste, der das versucht?', was man in C++ ziemlich oft erleben kann.
-
~fricky schrieb:
in der tat. da ist mal wieder dieses erstaunen: 'bin ich wirklich der erste, der das versucht?', was man in C++ ziemlich oft erleben kann.
Nö, das bist du sicherlich nicht. Aber wenn man länger C++ programmiert, gibt es eine relativ einfache Regel sich vor großen Ärger zu schützen. Man sollte keine C-Altlasten ohne groß nachzudenken mit C++ Mechanismen verwenden. Das geht oftmals in die Hose.
-
hustbaer schrieb:
- Welcher Typ sollte bei show_type("foo") rauskommen?
String Literale sind vom Type "array of n const char" bzw. "wchar_t" und sind static. Siehe §2.13.4 Absatz 1.
-
~john schrieb:
hustbaer schrieb:
- Welcher Typ sollte bei show_type("foo") rauskommen?
String Literale sind vom Type "array of n const char" bzw. "wchar_t" und sind static. Siehe §2.13.4 Absatz 1.
Und wie ist dann geregelt dass die Zuweisung
char* s = "foo";
legal ist?
EDIT: OK, hab den Absatz gefunden. Wieder einer dieser Hacks um kompatibel zu C zu bleiben. *kopf-schüttel*
-
~john schrieb:
~fricky schrieb:
in der tat. da ist mal wieder dieses erstaunen: 'bin ich wirklich der erste, der das versucht?', was man in C++ ziemlich oft erleben kann.
Nö, das bist du sicherlich nicht. Aber wenn man länger C++ programmiert, gibt es eine relativ einfache Regel sich vor großen Ärger zu schützen. Man sollte keine C-Altlasten ohne groß nachzudenken mit C++ Mechanismen verwenden. Das geht oftmals in die Hose.
ja, das schon. aber es nur ein bruchteil der möglichen fehlerquellen. schau doch mal hier in's C++ unterforum. ich lese es zwar ziemlich selten, aber jedesmal wenn ich mir's anschaue, weiss ich nicht, ob ich lachen oder weinen soll. nicht wegen der fragen, sondern wegen der antworten.