Fehler in der Dinkumware C++ Lib oder Standard?


  • Administrator

    Das folgende Problem:

    #include <vector>
    
    class X
    { }
    
    class C
    {
        // Attributes //
    private:
        std::vector<X*> m_XPointerVec;
    
        // Constructors & Destructor //
    public:
    
        // Methods //
    public:
        void add_x(X* pX) { m_XPointerVec.push_back(pX); };
        X* get_x_at(int i) const { return m_XPointerVec.at(i); }; // Error
    }
    
    void foo(C const& rC)
    {
        X* pX = rC.get_x_at(0); // Error
    }
    
    int main()
    {
        C c;
    
        X* pX = new X();
    
        c.add_x(pX);
    
        foo(c);
    
        delete pX;
    }
    

    Der Fehler, welcher entsteht, ist folgender:
    Can not convert from "X const*" to "X*"

    Wenn man std::vector in der Dinkumware Lib anschaut, merkt man auch wieso:

    template<typename T /*, bliblablub*/>
    class vector : /*blablabla*/
    {
    // bli bla blub
        typedef const T& const_reference;
    // bli bla blub
    }
    

    Müsste das nicht eher

    typedef T const& const_reference;
    

    heissen?

    Mir ist das in Visual Studio 2005 aufgefallen. Habe gerade keinen anderen Compiler zur Hand, um das mit anderen zu testen und kenne mich im Standard auch zu wenig aus, wie das dort genau definiert ist. Aber irgendwie finde ich das seltsam bis falsch.

    Erst recht, wenn ich dann sowas machen will:

    std::vector<X const*>
    

    Das würde dann gar nicht gehen.

    Grüssli



  • Dravere schrieb:

    Müsste das nicht eher

    typedef T const& reference;
    

    heissen?

    macht keinen unterschied. das const kann links oder rechts vom typ stehen.


  • Mod

    Den Fehler kann ich nicht nachvollziehen - möglicherweise hast du den Code versehentlich zu stark vereinfacht. Der gezeigt Code für vector ist absolut richtig, Elementtyp in vector<X*> ist X* - ein const_reference darf den Zeiger nicht verändern, folglich hat diese den Typ X* const& - wie der Compiler auf X const* kommt, erschließt sich aus dem gezeigten Code nicht.


  • Administrator

    diffent0r schrieb:

    macht keinen unterschied. das const kann links oder rechts vom typ stehen.

    Das stimmt eben nicht,

    const X* pX; // Das Objekt, auf welches pX zeigt, ist konstant
    X* const pX; // Der Zeiger ist konstant, das Objekt aber nicht.
    
    typedef const T& const_reference;
    // führt mit T = X* zu
    const X*& const_reference; // Eine Referenz auf einen nicht konstanten Zeiger, welcher auf ein konstantes Objekt zeigt.
    
    typedef T const& const_reference;
    // führt mit T = X* zu
    X* const& const_reference; // Eine Referenz auf einen konstanten Zeiger, welcher auf ein nicht konstantes Objekt zeigt.
    

    Unterschied bemerkt? 😉

    @camper,
    Schau dir den Code hier auch nochmals an, vielleicht siehst du dann das Problem 😉
    Die const_reference ist im Vector so, dass das Objekt nicht verändert werden darf und nicht der Zeiger 🙂

    Grüssli

    [Edit: Die Sache probiert noch ein wenig mehr zu verdeutlichen, bzw. berichtigen.]


  • Mod

    Dravere schrieb:

    typedef const T& const_reference;
    // führt mit T = X* zu
    const X*& const_reference; // Eine Referenz auf einen nicht konstanten Zeiger, welcher auf ein konstantes Objekt zeigt.
    

    So ist es gerade nicht. Es spielt keine Rolle, ob eine cv-Qualifizierung (unmittelbar) links oder rechts von einem Typbezeichner steht. Es spielt ebenfalls keine Rolle, ob dieser Typbezeichner aus einem elementareren Typen abgeleitet ist, weil es sich zufällig um ein Alias handelt, das per typedef oder als Templateparameter eingeführt wurde.

    const T modifiziert den Typ T so, dass dieser const-qualifiziert ist (ist T bereits const-qualifiziert, so ist, je nachdem, wo dieses Konstrukt auftaucht, das Programm entweder ill-formed oder - wie etwa bei typedef - das zusätzliche const wird ignoriert).
    Falls T zufällig ein Zeiger auf ein modifizierbares Objekt ist, so ist const T ebenso wie T const ein konstanter Zeiger auf ein modifizierbares Objekt.


  • Administrator

    Und wieso geht das bei meinem Compiler nicht? 😕
    Wenn ich genau den Code oben compilieren will, kommt die entsprechende Fehlermeldung raus. Und ich dachte, ich hätte das auch irgendwo mal gelesen, das dem so ist.

    Kannst du bitte mal den Code oben bei dir compileren? Sofern du VS2005 hast. Wenn das bei dir geht, mache ich wohl am besten mal eine Neuinstallation 😉
    Oder gibt es da irgendwelche Optionen, welche ich versehentlich verändert haben könnte?

    Grüssli



  • Dravere schrieb:

    diffent0r schrieb:

    macht keinen unterschied. das const kann links oder rechts vom typ stehen.

    Das stimmt eben nicht,

    Um es mal zusammengefasst zu schreiben:

    const int *;
    // ist identisch mit
    int const *; // Man beachte das der * noch immer rechts steht
    
    const int &;
    // ist identisch mit
    int const &;
    
    // Diese Schreibweise wird in einigen Quellen auch empfohlen weil sie den Vorteil hat
    // eindeutig zu sagen was konstant ist, lies:
    
    int const * const; // Integer-Konstante Zeiger-Konstante
    

    cu André



  • Dravere schrieb:

    Kannst du bitte mal den Code oben bei dir compileren? Sofern du VS2005 hast. Wenn das bei dir geht, mache ich wohl am besten mal eine Neuinstallation 😉
    Oder gibt es da irgendwelche Optionen, welche ich versehentlich verändert haben könnte?

    Folgender Code compiliert bei mir mit einer Warnung:

    #include <vector>
    
    class X
    { };
    
    class C
    {
      private:
        std::vector<X*> m_XPointerVec;
    
      public:
        void add_x(X* pX) { m_XPointerVec.push_back(pX); };
        X* get_x_at(int i) const { return m_XPointerVec.at(i); }; // Error
    };
    
    void foo(C const & rC)
    {
        X* pX = rC.get_x_at(0); // Error
    }
    
    int main()
    {
        C c;
        X* pX = new X();
        c.add_x(pX);
        foo(c);
        delete pX;
    }
    

    warning C4189: 'pX': Lokale Variable ist initialisiert aber nicht referenziert g:\projekte\forumnachtest\test1\test1.cpp 18

    Falls du zusätzlich auch noch die PC-Lint Auswertung haben willst:
    1. Information; Line 13; Loss of sign (arg. no 1) (int to unsigned int)
    2. Warning; Line 19; Symbol 'pX' (line 18) not subsequently referenced
    3. Information; Line 18; Location cited in prior Message
    4. Information; Line 24; Redundant parentheses ignored

    Compiliert auf dem VC-Compiler 8.1 (Visual Studio 2005 Standard)

    cu André


Anmelden zum Antworten