GCC 4.4.7 vs. GCC 4.7


  • Mod

    Bitte compilierbares (bzw. beim GCC 4.7 bis auf den Fehler compilierbares) Minimalbeispiel erstellen und posten.
    http://www.c-plusplus.net/forum/304133

    Die wichtige Frage, was PeerIDList ist, hast du auch noch nicht beantwortet. Die Antwort sollte sich aber aus dem Minimalbeispiel von selbst ergeben, also sieh lieber zu, dass du das Minimalbeispiel erstellst, anstatt diese Frage zu beantworten. Falls sich aus dem Minimalbeispiel nicht ergeben sollte, was PeerIDList ist, dann hast du den Fehler schon gefunden, denn dann weiss es der Compiler auch nicht*. Das ist einer der Vorteile beim Erstellen solcher Beispiele, dass man dabei meistens schon alleine den Fehler findet 🙂 .

    *: Warum der GCC 4.4 das dann trotzdem uebersetzt ist eine andere Frage. Ist vielleicht irgendein Include veraendert worden? Verlaesst du dich vielleicht irgendwo auf indirekte Includes der Standardheader? Waehrend die Header der Standardbibliothek des GCC 4.4 noch recht grosszuegig andere Header eingebunden haben, hat man in den letzten Jahren recht viele Anstrengungen unternommen, diese Indirektionen moeglichst raus zu machen (ausser dort, wo sie vom Sprachstandard vorgeschrieben sind). Dadurch ist eventuell irgendein Typ nicht bekannt. Aehnliches gilt eventuell auch, falls du unterschiedliche Versionen von Boost benutzt.



  • sven_ schrieb:

    Dadurch ist set:

    template<typename T>
            void
            HeterogeneousMap::set(const char * key, const T & t)
    

    Was du innerhalb von set tust, ist irrelevant. Wichtig ist nur die Signatur.

    Da dort ein const T& vorkommt, wobei T ein Templateparameter ist, kann das Templateargument beim Aufruf hergeleitet werden. Es reicht also,

    storage.set("peerIDList", peerList);
    

    zu schreiben.


  • Mod

    Ich vermute mal ein fehlendes template-Schlüsselwort (unterstellt, dass storage ein abhängiger Bezeichner ist). Andererseits hat gcc 4.4.7 das auch schon an solchen Stellen verlangt.



  • ich tippe auf Fehler beim includen


  • Mod

    camper schrieb:

    Ich vermute mal ein fehlendes template-Schlüsselwort (unterstellt, dass storage ein abhängiger Bezeichner ist).

    Ja... aber storage ist, wie er direkt in seinem zweiten Post zeigt, nicht abhängig von irgendwelchen Template-Argumenten deklariert. 😕



  • Hallo zusammen,

    sorry, hab mich ne Weile nicht gemeldet, da ich beruflich unterwegs war. Hier mal ein Minibeispiel, welches den Fehler erzeugt:

    #include <cstdlib>
    
    #include <string>
    #include <iostream>
    #include <map>
    #include <vector>
    #include "boost/any.hpp"
    
    typedef std::vector<int> PeerIDList;
    
    class HeterogeneousMap {
    public:
    
        HeterogeneousMap() {
        }
    
        virtual
        ~HeterogeneousMap() {
        }
    
        template<typename T>
        void
        set(const std::string & key, const T & t) {
    
            if (!storage[key].empty()) {
                if (storage[key].type() == typeid (T)) {
                    std::cerr << "fehler\n";
                    throw 0;
    
                }
                storage[key] = t;
            }
            else {
                storage[key] = t;
            }
        }
    
        template<typename T>
        T
        get(std::string key) {
            if (storage[key].empty()) {
                return T();
            }
            else {
    
                if (storage[key].type() == typeid (T)) {
                    return boost::any_cast<T>(storage[key]);
                }
                else {
    
                    std::cerr << "fehler\n";
                    throw 0;
                }
            }
        }
    
    private:
        std::map<std::string, boost::any> storage;
    
    };
    
    class BaseTimer {
    protected:
        HeterogeneousMap storage;
    
    };
    
    template <typename T>
    class ReferenceTimer : public BaseTimer {
    };
    
    template <typename T>
    class ReferenceMonitorTimer : public ReferenceTimer<T> {
    public:
    
        virtual void
        setPeerIDList(PeerIDList peerList) {
            BaseTimer::storage.set("peerIDList", peerList);
        }
    
        virtual PeerIDList
        getPeerIDList() {
            return BaseTimer::storage.get<PeerIDList>(std::string("peerIDList"));
    
        }
    };
    
    /*
     *
     */
    int
    main(int argc, char** argv) {
    
        ReferenceMonitorTimer<int> timer;
    
        PeerIDList list1;
        timer.setPeerIDList(list1);
        PeerIDList list2 = timer.getPeerIDList();
    
        return 0;
    }
    

    Als Fehler erhalte ich:

    g++ -std=c++0x   -c -g -s -MMD -MP -MF "build/Debug/GNU_1-Linux-x86/main.o.d" -o build/Debug/GNU_1-Linux-x86/main.o main.cc
    main.cc: In member function ‘virtual PeerIDList ReferenceMonitorTimer<T>::getPeerIDList()’:
    main.cc:91:55: error: expected primary-expression before ‘>’ token
    gmake[2]: *** [build/Debug/GNU_1-Linux-x86/main.o] Error 1
    

    Ich nutze um auf Centos6 eine Gcc 4.7 Umgebung zu haben die RedHat DevTools 1.1. Lasse ich im Aufruf <PeerIDList> weg, bekommt er das Template nicht mehr aufgelöst. Es sieht für mich aus, als ob er PeerIDList im Kontext nicht kennt, aber wieso????

    Besten Danke für Eure Unterstützung im Vorraus.



  • template <typename T>
    class ReferenceMonitorTimer : public ReferenceTimer<T> {
    public:
    
        virtual void
        setPeerIDList(PeerIDList peerList) {
            BaseTimer::storage.set("peerIDList", peerList);
        }
    
        virtual PeerIDList
        getPeerIDList() {
            return BaseTimer::storage.get<PeerIDList>(std::string("peerIDList"));
    
        }
    };
    

    Das ist mal tricky. BaseTimer hängt nicht von T ab. Aber die Basis von ReferenceMonitorTimer<T> ist ReferenceTimer<T> , was von BaseTimer erbt. Dem Compiler ist jedenfalls in der ersten Lookup-Phase nicht bekannt, dass BaseTimer wirklich eine Basisklasse von ReferenceMonitorTimer<T> ist.

    Probier mal das hier:

    return this->storage.template get<PeerIDList>(std::string("peerIDList"));
    

    Mit this-> dürfte klar sein, dass storage ein Element einer Basis ist. Weil in der direkten Basis T auftaucht, wird das Lookup für storage verzögert. Weil der Compiler storage in der ersten Lookup-Phase nicht kennt, müssen wir ihm sagen, dass es sich bei get um ein Template handelt und dass damit das < eine "spitze Template-Klammer" statt des kleiner-als-Operators ist.



  • Das ist ja mal geil. Es geht! Darf man noch fragen was storage.template ist? Kenne ich bisher nicht. Heißt es also, es ist problematisch, von templates zu erben und dann elemente der basis zu nutzen? kann man dies eventl. durch eine bessere basismethode fixen?

    sven_



  • sven_ schrieb:

    Das ist ja mal geil. Es geht! Darf man noch fragen was storage.template ist?

    Hab ich ja versucht zu erklären. storage wurde nicht in ReferenceMonitorTimer<T> definiert. Und weil die Basis von ReferenceMonitorTimer<T> auch von T abhängt, ist storage in this->storage ein von einem Template-Parameter abhängiger Name. Wenn der Compiler das erste mal über das Template guckt, also bevor Du es instantiierst, dann weiß er nicht, was storage ist und dass es ein Member-Template namens get hat. get könnte auch ein Datenelement sein, was du dann mit dem Kleiner-Als-Operator mit etwas anderes zu vergleichen versuchst. Es gibt hier also eine Mehrdeutigkeit, die manuell aufgehoben werden muss. Dazu schreibt man dann das template -Schlüsselwort vor das get . Dann weiß der Compiler, dass get ein Template ist. So etwas ähnliches kennst Du wahrscheinlich schon. Manchmal muss man an einigen Stellen ein typename einbauen. Z.B. hier:

    template<class T>
    class foo
    {
       vector<T> bar;
    
       void transmogrify()
       {
          typename vector<T>::iterator it = bar.begin();
          // ^^^^^
       }
    };
    

    Und so ähnlich ist das mit template für Member-Templates auch.

    Stichwörter für Dich zum Recherchieren:
    Two-Phase-Lookup
    Dependent Names



  • Hallo kkaw,

    das mit der stufenweisen Auflösung hab ich verstanden. Das keyword template kannte ich an der Stelle allerdings nicht. Danke für die Recherche-Tips, da werde ich nebenbei mal ein wenig die Suchmaschine bemühen. 🙂

    Vielen Dank.


Anmelden zum Antworten