problem mit numerical_limits<int>::max()



  • wozu brauchst du denn das max-makro?

    wieso versuchst du es denn nicht mal mit #define NOMINMAX, dann #include <windows.h> - haben doch nun auch schon 2 gesagt, dass es das behebt...

    wenn du ne max-fkt willst, dann nimm std::max ()...

    hf



  • 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.



  • vlad_tepesch schrieb:

    da das verwendete eine templateklasse ist, welche im header implementiert ist, hätte ein undef unvorhersehbare Folgen

    das undef hätte nur dann unvorhersehbare Folgen wenn du das Makro das dir irgendwo aus dem windows.h header untergejubelt wurde, auch benutzen willst. Das Makro wird in anderen headern und in deinem Code nicht benutzt, deshalb kannst du es getrost per undef entsorgen, bevor es sich wie hier in deine header schleicht und deine Definitionen verhunzt. Was du hier siehst ist eines der wichtigsten Argumente gegen Makros in Headern, vor allem wenn sie so prägnant kurze namen haben - je geläufiger der Name desto größer die Wahrscheinlichkeit dass irgendwer den Namen woanders benutzt, nicht ahnend dass das Makro ihm den Code zerstört. Deshalb: windows.h nur mit vorherigem #define NOMINMAX benutzen und wenn möglich als allerletztes einbinden, damit diese gruselige Makropolitik dir nicht später eingebundene Header zerpflügen kann.

    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.

    Deshalb solltest du dafür sorgen dass diese bescheuerten Makros nie, nie, nie irgendwo präsent sind, wo du noch Header einbindest oder gar in Headern selbst.



  • vlad_tepesch schrieb:

    ich habe ja keinen einfluss darauf, ob das macro da ist, oder nicht

    Doch. Makros kann man #undef en.

    vlad_tepesch schrieb:

    da das verwendete eine templateklasse ist, welche im header implementiert ist, hätte ein undef unvorhersehbare Folgen, es sei denn man könnte die alte definition speichern und danach wieder herstellen.

    Wieso brauchst du das Makro nachher überhaupt noch? In C++ sollte das sowieso nicht verwendet werden.



  • meine frage war ja eigendlich, ob ma irgendwie die definition von max sichern kann, dann ein undef und dann redefinieren, ohne dass ich de ursprüngliche definition kenn muss. so ähnich wie mit praga pushes und pops



  • Vor jedem windows.h-Include ganz einfach #define NOMINMAX und fertig.

    MfG SideWinder



  • Nexus schrieb:

    Doch. Makros kann man #undef en.

    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


  • Mod

    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
    #endif
    

    Oder 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) )
    #endif
    

    Problem 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) )
    #endif
    

    Problem 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
    #endif
    

    Die 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
    #endif
    

    Nein, das Problem ist hier, dass SAVEDMAX nur als Textersetzung für max dient. Die Funktionalität von max wird 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 SAVEDMAX mit max textuell 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
    #endif
    

    Die 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)
    #endif
    

    Worauf 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?


  • Mod

    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
    

  • Mod

    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);
      };
    

Anmelden zum Antworten