Mal kann er eine Memberfunktion aufrufen und Mal nicht.



  • Das hier geht:

    UID u(v);
        Test t2( u ); 
        t2.fct();
    


  • Die Zeile

    Test    t2(UID(v));
    

    scheint als Funktionsdeklaration aufgefasst zu werden.

    Was mich allerdings ein wenig erstaunt, da UID(v) eigentlich keine Parameterdeklaration ist...



  • tandem schrieb:

    Das hier geht:

    UID u(v);
        Test t2( u ); 
        t2.fct();
    

    Ja stimmt, hatte ich auch schon rausgefunden, aber leider vergessen mit reinzuschreiben.

    Ich versteh aber nicht warum es so geht, aber wenn ich es als temporäres Objekt habe nicht. Ist mir nicht klar, zumal der Fehler nicht beim Aufbau des Objektes passiert, sondern später.

    😞



  • Ich glaube wirklich dass es ein Bug Report wert ist!



  • Also folgende Sachen gehen auch noch:

    Test t2( UID(static_cast<const char*>(v)) );
    

    und

    Test t2( (UID(v)) );
    

    Keine Ahnung was da läuft...
    Insbesondere das Zweite gibt mir zu denken.



  • Du hast meinen Beitrag wohl übersehen, da du 5 Sekunden später auch gleich gepostet hast... 🙂

    Unter MSVC++ erhält man ebenso einen Fehler. Wie gesagt erkennt der Compiler die Zeile als Funktionsdeklaration. Ich bin selbst ein wenig verwirrt; eventuell hat das mit der Auswertungs-/Parserreihenfolge des Kompilierens zu tun...



  • Nexus schrieb:

    Du hast meinen Beitrag wohl übersehen, da du 5 Sekunden später auch gleich gepostet hast... 🙂

    Ja hatte ich wohl.

    Nexus schrieb:

    Unter MSVC++ erhält man ebenso einen Fehler. Wie gesagt erkennt der Compiler die Zeile als Funktionsdeklaration. Ich bin selbst ein wenig verwirrt; eventuell hat das mit der Auswertungs-/Parserreihenfolge des Kompilierens zu tun...

    Und was kann ich dann jetzt daraus schließen? Haben beide Compiler einen bug? Ist dies ein Problem im Standard? Habe keine Ahnung. Ich meine es gibt ja workarounds, wie tandem ja schon gezeigt hat. Aber ist dies die Lösung?

    Gruß



  • Das Problem läßt sich auf folgende Zeile reduzieren:

    void foo (int (bar));
    

    MSVC, GCC, BCC und Comeau compilieren das anstandslos. Bei BCC resultiert typeid (foo).name () in "void (*)(int)"; was aus dem bar wird, ist mir momentan nicht nachvollziehbar.

    Ich vermute ein parserbedingtes Defizit. Sobald man bar durch einen bekannten Typen ersetzt, z.B. int, wird das Argument zu einem Funktionszeiger ("void ()(int ()(int))").


  • Administrator

    Sehr bekanntes Problem. Eine etwas bekanntere Version:

    std::vector<double> vec(
    	std::istream_iterator<double>(std::cin),
    	std::istream_iterator<double>());
    

    Hier passiert der gleiche Fehler.
    Sobald man diese Version verwendet, um ein Objekt zu konstruieren, darf man leider nicht bei allen Argumenten einen Typen angeben. (Ich hoffe den Satz kann man verstehen :))
    Also sowas würde bereits wieder funktionieren:

    std::istream_iterator<double> iend;
    
    std::vector<double> vec(
    	std::istream_iterator<double>(std::cin),
    	iend);
    

    Entweder man nimmt die Argumente raus und erstellt sie, bevor man sie dem Konstruktor übergibt. Oder man verwendet die alternative Schreibeweise:

    std::vector<double> vec =
    	std::vector<double>(
    		std::istream_iterator<double>(std::cin),
    		std::istream_iterator<double>());
    
    // bzw. auf das andere Beispiel bezogen:
    Test t2 = Test(UID(v));
    
    // bzw. hier sogar, da der Konstruktor von Test nicht explicit ist
    // und nur ein Argument erwartet wird:
    Test t2 = UID(v);
    

    Hat also überhaupt nichts mit einem Bug zu tun, sondern ist absolut korrektes Standardverhalten. Auch wenn der Standard in dem Bereich ein wenig unsinnig ist. Ich habe bisher keinen Fall kennen gelernt, wo eine Funktionsdeklaration in einer Funktion wirklich sinnvoll war.

    Grüssli



  • Dravere schrieb:

    Sehr bekanntes Problem.

    Dann sieh dir bitte mal meine Reduktion an und sage mir, was der Compiler mit bar macht.



  • Wusste ich gar nicht, dass es bei der Funktionsdeklaration gültige Syntax ist, den Parameternamen einzuklammern.


  • Administrator

    audacia schrieb:

    Dravere schrieb:

    Sehr bekanntes Problem.

    Dann sieh dir bitte mal meine Reduktion an und sage mir, was der Compiler mit bar macht.

    Er lässt es dort, für ihn ist es das gleiche wie:

    void foo(int bar);
    

    Diese Klammerung kann man zum Teil auch sinnvoll einsetzen:

    template<typename T, std::size_t N>
    std::size_t getArraySize(T const (&arr)[N])
    {
      return N;
    }
    

    Da hast du auch solche Klammern, nur sind sie hier von belang. Beim anderen sind sie halt überflüssig.

    Grüssli



  • Dravere schrieb:

    audacia schrieb:

    Dravere schrieb:

    Sehr bekanntes Problem.

    Dann sieh dir bitte mal meine Reduktion an und sage mir, was der Compiler mit bar macht.

    Er lässt es dort, für ihn ist es das gleiche wie:

    void foo(int bar);
    

    Aah, daß der Parameter in Klammern gesetzt werden darf, war mir nicht mehr bewußt.

    Dravere schrieb:

    Diese Klammerung kann man zum Teil auch sinnvoll einsetzen:

    template<typename T, std::size_t N>
    std::size_t getArraySize(T const (&arr)[N])
    {
      return N;
    }
    

    Tatsächlich - ich kann mich sogar erinnern, das schon einmal benutzt zu haben.

    Ist wohl doch schon etwas spät 🤡



  • Danke fuer die Klaerung.

    Es ist also ein Problem mit der Kontextsensitivitaet von C/C++. Weiss jemand, ob dies vielleicht in der zukuenftigen Version des Standards geaendert wird.

    Gruss


Anmelden zum Antworten