Zeiger auf geerbtes, templateparameterabhängiges Memberobjekt [erledigt]


  • Mod

    Folgender kurzer Code:

    template <typename T> struct foo
    {
      T data;
    };
    
    template<typename T> struct bar: public foo<T>
    {
      typedef foo<T> Super;
      void some_func()
      {
        T* ptr = & (Super::data);    
      }
    };
    
    int main()
    {
      bar<int> b; 
      b.some_func();
    }
    

    Gibt den Fehler:

    11: error: cannot convert ‘int foo<int>::*’ to ‘int*’ in initialization
    

    😕
    Wie kann der Compiler aus dem Ausdruck &(Super::data) etwas vom Typ ‘int foo<int>::*’ herauslesen? Mir ist klar, dass ich auch einfach &(this->data) schreiben kann und dann geht's, aber ich möchte wissen, warum meine Schreibweise nicht funktioniert.

    Wenn ich das 1:1 ohne die Templates mache, geht das schließlich auch:

    struct foo
    {
      int data;
    };
    
    struct bar: public foo
    {
      typedef foo Super;
      void some_func()
      {
        int* ptr = & (Super::data);    
      }
    };
    


  • Der Compiler interpretiert das fälschlicherweise als "Pointer-to-member", ähnlich wie ein Memberfunktionszeiger. Der speichert den relativen Offset zur Klasse, für den Zugriff benötigst du ein Objekt.

    Soweit ich weiss, ist aber & (Super::data) für einen Pointer-to-member syntaktisch nicht korrekt, die Klammern dürfen nicht stehen. Der Code mit Klammern sollte also funktionieren, unter MSVC++ und Comeau Online tut er das auch. Ich vermute einen Compilerbug in g++.


  • Mod

    Nexus schrieb:

    Der Compiler interpretiert das fälschlicherweise als "Pointer-to-member", ähnlich wie ein Memberfunktionszeiger. Der speichert den relativen Offset zur Klasse, für den Zugriff benötigst du ein Objekt.

    Soweit ich weiss, ist aber & (Super::data) für einen Pointer-to-member syntaktisch nicht korrekt, die Klammern dürfen nicht stehen. Der Code mit Klammern sollte also funktionieren, unter MSVC++ und Comeau Online tut er das auch. Ich vermute einen Compilerbug in g++.

    Danke für den Test auf anderen Compilern. Ich war schon sehr verwirrt, wie der zu dieser Interpretation kommt. Ich habe auch mal den intel-Compiler drauf losgelassen und der schluckt es auch. Hätte ich vielleicht gleich tun sollen, aber eigentlich gehe ich bei Standardfragen immer davon aus, dass eher der g++ recht hat :p .

    Dann ist das Thema wohl schon erledigt und ich werde mal einen Bugreport aufsetzen.


  • Mod

    Nexus schrieb:

    Soweit ich weiss, ist aber & (Super::data) für einen Pointer-to-member syntaktisch nicht korrekt, die Klammern dürfen nicht stehen.

    Das kann ich übrigens nach etwas Standardlesen bestätigen. Die Passage ist sogar extrem eindeutig:

    C++ Standard 5.3.1-3 schrieb:

    A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. [ Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is &unqualified-id pointer to member, even within the scope of the unqualified-id’s class. — end note ]

    Hervorhebung durch mich.


Anmelden zum Antworten