In Datei schreiben
-
@tomy86
Angenommen...
Ich entwickle eine Library "Foo" in der viel inline implementiert ist.
Ich brauche in dieser Librarystd::numeric_limits<streamsize>::max()
.
Ich schreibe also// Foo.hpp #define NOMINMAX #include <windows.h> // Weil ich irgendwo WinAPI Funktionen brauche // ... inline void Bar() { // ... auto const m = std::numeric_limits<streamsize>::max(); // ... }
Und jemand der meine Library verwendet schreibt
#include <windows.h> #include <Header File einer anderen Library welches dummerweise die min und max Macros aus windows.h braucht.h> #include <Foo.hpp>
Dann gibt's ein Problem, und zwar weil zu dem Zeitpunkt wo
windows.h
das erste mal inkludiert wurdeNOMINMAX
nicht definiert war.
Also wurden diemin
undmax
Makros definiert.
Hässlicher Fix:#include <windows.h> #include <Header File einer anderen Library welches dummerweise die min und max Macros aus windows.h braucht.h> #undef min #undef max #include <Foo.hpp>
Und eine Möglichkeit solchen Problemen aus dem Weg zu gehen, so dass der Anwender meiner Library "Foo" diesen hässlichen Workaround nicht machen muss, ist eben
(std::numeric_limits<streamsize>::max)()
zu schreiben.
-
Es gibt da noch eine Möglichkeit.
//kann man von Boost nehmen oder selber definieren #define BOOST_PREVENT_MACRO_SUBSTITUTION std::numeric_limits<std::streamsize>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()
Hat den Vorteil, dass niemand den Workaround versehentlich entfernt (bei Copy-Paste zum Beispiel). Bei
(std::numeric_limits<streamsize>::max)
ist nicht erkennbar, warum da redundante Klammern stehen.
Wer sich aber überBOOST_PREVENT_MACRO_SUBSTITUTION
wundert, kann das Googlen.
-
Ah, ok. Und die Klammern haben ihre Wirkung, da das max zu numeric_limits gehört und somit zusammen abgearbeitet wird? Also zb so wie bei (3+3)*3? Wobei hier 3+3 das numeric_limit::max entspricht und *3 das max Makro aus windows.h?
-
string dateiname()
{
string name;
cout << "Bitte gib den Dateinamen an: ";
cin >> name;
return name.append(".txt");
}geht das auch, wenn ich "test.txt" eingebe?
-
Die Klammern haben hier bloss den Sinn dass der Präprozessor es nicht mehr als Kandidat für ein Function-Style-Makro durchgehen lässt.
Wobei ich die von TyRoXx vorgeschlagene Variante eigentlich besser finde. Aus den von ihm genannten Gründen.
-
hardware schrieb:
string dateiname()
{
string name;
cout << "Bitte gib den Dateinamen an: ";
cin >> name;
return name.append(".txt");
}geht das auch, wenn ich "test.txt" eingebe?
Ja auch das geht. Man könnte sogar test.exe eingeben, aber da ans Ende das .txt angehangen wird, wird die Datei in jedem Fall auch als Textdatei gehandhabt.
hustbaer schrieb:
Die Klammern haben hier bloss den Sinn dass der Präprozessor es nicht mehr als Kandidat für ein Function-Style-Makro durchgehen lässt.
Wobei ich die von TyRoXx vorgeschlagene Variante eigentlich besser finde. Aus den von ihm genannten Gründen.
Die Frage diente in erster Linie dem Verständnis dafür, wie die Klammern arbeiten. Und ob das immer so ist, oder nur in diesem speziellen Fall.
-
@tomy86
Also was die Klammern bewirken muss man sich 2x angucken.
Erstmal was den Präprozessor betrifft und dann nochmal was die C++ Grammatik angeht.Was den Präprozessor angeht hab ich ja schon geschrieben. Dass der PP hier das "max" in den Klammern nicht mehr als Name eines Function-Style Makros in Betracht zieht ist ja der erwünschte Effekt. Die genauen Grammatikregeln müsstest du ggf. selbst nachgucken.
Danach kommt die "eigentliche" C++ Übersetzung.
Wenn ich das richtig verstehe (ich hoffe ich erzähle jetzt keinen Unsinn)...Ein Funktionsaufruf ist in der C++ Grammatik eine postfix-expression
und zwar in der Form
postfix-expression ( expression-list
opt)
Der erste Teil "benennt" dabei die Funktion, der Teil in der Klammer ist die optionale Parameterliste.std::numeric_limits<streamsize>::max
als solches ist eine qualified-id, und damit automatisch auch eine postfix-expression.
Passt also oben als erster Teil des Funktionsaufrufs (der Teil der die Funktion "benennt").(std::numeric_limits<streamsize>::max)
würde an der Stelle dann als primary-expression geparsed,
und zwar in der Form
( expression )
.
Da eine primary-expression auch eine postfix-expression ist, funktioniert das auch als 1. Teil des Funktionsaufrufs.D.h. beides geht schonmal als valide C++ Grammatik durch.
Das bedeutet jetzt nicht automatisch dass auch der Effekt beider Expressions gleichbedeutend ist, aber in diesem Fall ist er es halt
(Heisst: manchmal ist(x)
an einer Stelle wo man auch nurx
schreiben könnte eben nicht gleichbedeutend mit nurx
.)
-
@hustbaer
Vielen Dank, für die ausführliche Erklärung