problem mit numerical_limits<int>::max()
-
Nexus schrieb:
Doch. Makros kann man
#undefen.das sollte man aber nicht in headern machen, die von anderen benutzt werden
Nexus schrieb:
Wieso brauchst du das Makro nachher überhaupt noch? In C++ sollte das sowieso nicht verwendet werden.
das ändert ja nix daran, dass es automatisch da ist und mancher trotzdem verwendet
-
SideWinder schrieb:
Vor jedem windows.h-Include ganz einfach #define NOMINMAX und fertig.
MfG SideWinder
nur habe ich keinen zugriff auf diese files und muss die umgebung, in der ich includet werde, nehmen, wie ich sie bekomme
-
Es mag sinnvoll sein, statt eines #undef eine Fehlermeldung auszugeben. Denn grundsätzlich ist davon auszugehen, dass es sich hier um einen Konfigurationsfehler handelt, schließlich darf kein Header der Standardbibliothek mit vorhandenem min/max-Makro verwendet werden. z.B. so
#if defined max || defined min #if defined __WINDOWS__ && !defined NOMINMAX #error Please define NOMINMAX before including <windows.h> #else #error This header cannot function properly with min/max-macros defined #endif #endifOder man schwächt das Ganze ab zu einer Warnung mit folgendem #undef
Ein temporäres umdefinieren kann man auch erwägen
#ifdef max #undef max #define max max #endif ... #ifdef max #undef max #define max( a, b ) ( ((b) < (a)) ? (a) : (b) ) #endifProblem hierbei ist natürlich, dass man den vorherigen Inhalt des Makros nicht kennt, und ihn somit nicht sicher wiederherstellen kann.
-
vlad_tepesch schrieb:
ich habe ja keinen einfluss darauf, ob das macro da ist, oder nicht:
headerdatei meiner klasse
#include <limits> template<class T> class MyClass { public: MyClass() :m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) {} T m_min; T m_max; }wenn jetzt an irgend einer Stelle im Projekt (die ich nicht kenne und auf die ich keinen Einfluss habe) dieser header includiert wird, wo dieses max, oder min makro präsent ist, gehts net.
Kann es sein, dass Dir die Includeguards fehlen?
#ifndef __MEIN_HEADER_H__INCLUDED #define __MEIN_HEADER_H__INCLUDED //code #endif
-
camper schrieb:
mit folgendem #undef
Ein temporäres umdefinieren kann man auch erwägen
#ifdef max #undef max #define max max #endif ... #ifdef max #undef max #define max( a, b ) ( ((b) < (a)) ? (a) : (b) ) #endifProblem hierbei ist natürlich, dass man den vorherigen Inhalt des Makros nicht kennt, und ihn somit nicht sicher wiederherstellen kann.
Ich bin mir nicht ganz sicher ob man Makros verschachteln kann (eigentlich will ichs auch nicht wissen weil ichs nicht anwenden will), aber rein hypotetsich, geht sowas?
#ifdef max #define SAVEDMAX max #undef max #endif ... #ifdef SAVEDMAX #define max SAVEDMAX #undef SAVEDMAX #endif(Oh Graus...)
Tachyon schrieb:
Kann es sein, dass Dir die Includeguards fehlen?
#ifndef __MEIN_HEADER_H__INCLUDED #define __MEIN_HEADER_H__INCLUDED //code #endifDie helfen leider auch nicht weiter:
#include <windows.h> //ab hier ist das Makro max definiert und verändert alles was an max noch kommt #include "myheader.h" //jedes Vorkommen von max in myheader.h wird HIER durch das Makro ersetzt - woanders vielleicht nicht...
-
pumuckl schrieb:
Ich bin mir nicht ganz sicher ob man Makros verschachteln kann (eigentlich will ichs auch nicht wissen weil ichs nicht anwenden will), aber rein hypotetsich, geht sowas?
#ifdef max #define SAVEDMAX max #undef max #endif ... #ifdef SAVEDMAX #define max SAVEDMAX #undef SAVEDMAX #endifNein, das Problem ist hier, dass
SAVEDMAXnur als Textersetzung fürmaxdient. Die Funktionalität vonmaxwird eben nicht übertragen.
-
pumuckl schrieb:
[...]
Ich bin mir nicht ganz sicher ob man Makros verschachteln kann (eigentlich will ichs auch nicht wissen weil ichs nicht anwenden will), aber rein hypotetsich, geht sowas?#ifdef max #define SAVEDMAX max #undef max #endif ... #ifdef SAVEDMAX #define max SAVEDMAX #undef SAVEDMAX #endif(Oh Graus...)
Ich denke nicht, da hierbei nur
SAVEDMAXmitmaxtextuell ersetzt wird.pumuckl schrieb:
Tachyon schrieb:
Kann es sein, dass Dir die Includeguards fehlen?
#ifndef __MEIN_HEADER_H__INCLUDED #define __MEIN_HEADER_H__INCLUDED //code #endifDie helfen leider auch nicht weiter:
#include <windows.h> //ab hier ist das Makro max definiert und verändert alles was an max noch kommt #include "myheader.h" //jedes Vorkommen von max in myheader.h wird HIER durch das Makro ersetzt - woanders vielleicht nicht...Ich ging hierbei davon aus, dass eigentlich gar keine Konflikte mit den Windows-Defines bestehen, sondern dass die eigentlich Ursache des Problems die fehlenden Includeguards sind.
-
Tachyon schrieb:
Kann es sein, dass Dir die Includeguards fehlen?
hab ich jetzt mal der einfach halber weggelassen
an campers ersten vorschlag hab ich auch schon gedacht und werd ihn wohl benutzen. (es ist hoffentlich niemand so dämlich die min und max makros umzudefineren, dass sie was anderes machen)
ich hätt halt gehofft das jemand ne andere alternative kennt, das makro zu konservieren, oder den präprozessor für bestimmte codeteile abzuschalten.
ZB mittels pragmas, oder so.pumuckles vorschlag, geht definitv nicht.
-
vlad_tepesch schrieb:
an campers ersten vorschlag hab ich auch schon gedacht und werd ihn wohl benutzen.
Würde ich auch nicht machen. Ich würds einfach analog zu den Standardheadern wie <limits> machen, die auch davon ausgehen, dass niemand so bescheuert ist, ein Makro wie max zu defineren, bevor er die Header einbindet. Du könntest zwar wie vorgehabt nachgeben nach dem Motto "okay, windows.h definiert das Makro max, dem muss ich rechnugn tragen", aber wenn du so anfängst kommt bald eine bestimmt sehr nützliche Bibliothek, die in ihren Headern vielleicht folgendes stehen hat:
#ifndef OHNOEZ #define pair 2 #define vector int[3] #define string const char* #define if( arg ) maybe( (arg) ) #define cout (printf("ich mach dir alles kaputt!"), cerr) #endifWorauf ich hinauswill: mach dir nicht überflüssige Arbeit, nur weil unter Umständen jemand ausversehen ein Makro definiert haben könnte das genauso heißt wie eine Funktion die im Standard vorhanden ist. Es ist nicht deine Aufgabe das wieder gut zu machen. Es ist Aufgabe des makro-Herstellers, seine Kreation möglichst vor der Publizierung zu entsorgen*, bzw. Aufgabe des Klienten, äußerst vorsichtig mit solchen Biblotheken umzugehen.
_____________________
* ich weiß dass windows.h eine C-API ist und mit Standard-C++ daher nichts am Hut haben muss. Umso schlimmer dass alle Welt immernoch fröhlich und ungeschützt die Makrohölle in ihre C++-Codes importiert. Gibts keinen C++ windows.h-Wrapper?
-
Mein erster Vorschlag bestand darin, eine intelligente Fehlermeldung zu produzieren (und das ist auch das Einzige, was ich selbst tun würde - wenn überhaupt).
Grundsätzlich ist es richtig, dass man nicht mit jedem Unfug, den man vor Einbinden des Headers machen kann, umgehen können muss. Praktisch stellt sich aber eher die Frage, ob es in bestimmten bekannten Fällen zuviel verlangt ist. Da eine solche Überprüfung in jedem einzelnen Header die Wartbarkeit nicht fördert, ist sie eher etwas für einen zentralen Konfigurationsheader, den man im Falle einer etwas umfangreicheren Bibliothek ohnehin oft hat, um sich auf das konkrete System, für das kompiliert wird, einzustellen (natürlich muss man sich auch dabei intelligent anstellen: die Überprüfung darf nicht durch include-Guards geschützt sein).
-
Hallo,
es gibt sogar Compiler (Microsoft/g++), die die #pragmas push_macro/pop_macro kennen:
http://msdn.microsoft.com/en-us/library/2bs04eza(VS.80).aspx
MfG,
Probe-Nutzer
-
das scheint ja genau das zu sein was ich suche, leider functioniert das pop_macro irgend wie nich:
#ifdef min # pragma push_macro("min") # undef min # define popmin #endif #ifdef max # pragma push_macro("max") # undef max # define popmax #endif MyClass() :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) {}; MyClass(T i) :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) { operator=(i); }; #ifdef popmax # pragma pop_macro("max") # undef popmax #endif #ifdef popmin # pragma pop_macro("min") # undef popmin #endif
-
Probe-Nutzer schrieb:
Hallo,
es gibt sogar Compiler (Microsoft/g++), die die #pragmas push_macro/pop_macro kennen:
http://msdn.microsoft.com/en-us/library/2bs04eza(VS.80).aspx
MfG,
Probe-Nutzer
In der gcc-Dokumentation kann ich nichts dazu finden. Die MSDN-Beschreibung lässt darauf schließen, dass das Ganze nur für Objektmakros funktioniert.
-
Wenn man die Makros nicht einfach #undefen kann (ja das kommt vor), geht auch folgende Methode (auch wenns nicht mehr ganz so schön aussieht):
#define NO_MACRO MyClass() :m_count(0) ,m_min(numeric_limits<T>::max NO_MACRO ()) ,m_max(numeric_limits<T>::min NO_MACRO ()) ,m_sum(0) {}; MyClass(T i) :m_count(0) ,m_min(numeric_limits<T>::max NO_MACRO ()) ,m_max(numeric_limits<T>::min NO_MACRO ()) ,m_sum(0) { operator=(i); };
-
@derkuchen
danke, es ist zwar wirklich nicht mehr so schön, aber das löst das Problem auf sicherste und unkomplizierteste weise.
-
camper schrieb:
Probe-Nutzer schrieb:
Hallo,
es gibt sogar Compiler (Microsoft/g++), die die #pragmas push_macro/pop_macro kennen:
http://msdn.microsoft.com/en-us/library/2bs04eza(VS.80).aspx
MfG,
Probe-Nutzer
In der gcc-Dokumentation kann ich nichts dazu finden.
Ich habe irgendwo für gcc geschriebenen Code gesehen, der das verwendet, und ich habe jetzt auch noch einmal gesucht, und das hier:
http://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html
gefunden.
camper schrieb:
Die MSDN-Beschreibung lässt darauf schließen, dass das Ganze nur für Objektmakros funktioniert.
Siehe unten.
vlad_tepesch schrieb:
das scheint ja genau das zu sein was ich suche, leider functioniert das pop_macro irgend wie nich:
#ifdef min # pragma push_macro("min") # undef min # define popmin #endif #ifdef max # pragma push_macro("max") # undef max # define popmax #endif MyClass() :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) {}; MyClass(T i) :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) { operator=(i); }; #ifdef popmax # pragma pop_macro("max") # undef popmax #endif #ifdef popmin # pragma pop_macro("min") # undef popmin #endifIch habe das, an dein Beispiel angelehnt, mit dem VS2005, Service Pack 1, versucht:
#include <limits> #include <iostream> #include <windows.h> using namespace std; #ifdef min # pragma push_macro("min") # undef min # define popmin #endif #ifdef max # pragma push_macro("max") # undef max # define popmax #endif template<class T> class MyClass { public: MyClass() :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) {}; MyClass(T i) :m_count(0) ,m_min(numeric_limits<T>::max()) ,m_max(numeric_limits<T>::min()) ,m_sum(0) { operator=(i); }; private: int m_sum; int m_min; int m_max; int m_count; }; #ifdef popmax # pragma pop_macro("max") # undef popmax #endif #ifdef popmin # pragma pop_macro("min") # undef popmin #endif int main(int argc, char* argv[]) { int a = 6; int b = 7; MyClass<int> test; MyClass<int> test2; cout << max(a, b) << endl; return 0; }und es funktioniert.
MfG,
Probe-Nutzer
-
und es funktioniert.
Der teil funktioniert ja auch, aber die makros min/max, werden nicht richtig redefiniert.
(ich arbeite mit vc++ 8 SP1)
-
vlad_tepesch schrieb:
und es funktioniert.
Der teil funktioniert ja auch, aber die makros min/max, werden nicht richtig redefiniert.
(ich arbeite mit vc++ 8 SP1)
Ok, kann ich jetzt nichts weiter dazu sagen, mein Code liefert jedenfalls das Maximum wieder. Aber wir haben hier jetzt auch schon einige Lösungen gesehen, insofern betrachte man die pop_macro/push_macro-Idee nur als eine Anmerkung von mir.
MfG,
Probe-Nutzer
-
Probe-Nutzer schrieb:
Ich habe irgendwo für gcc geschriebenen Code gesehen, der das verwendet, und ich habe jetzt auch noch einmal gesucht, und das hier:
http://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html
gefunden.
Bei der PDF-Version fehlen die Abschnitte 5.52.11 und 5.52.12 - das müsste man gewusst haben...
