Initialisierung einer Member-Referenz ueber Uniform Initialization



  • Hallo,

    Wieso klappt Uniform Initialization fast ueberall, nur bei Member-Referenzen nicht?

    struct foo
    {};
    
    struct bar
    {
        bar(foo& f)
            : f{f}
        {}
    
        foo& f;
    };
    
    int main()
    {
        foo f;
        bar b{f};
    }
    

    prog.cpp: In constructor 'bar::bar(foo&)':
    prog.cpp:7:14: error: invalid initialization of non-const reference of type 'foo&' from an rvalue of type '<brace-enclosed initializer list>'

    https://ideone.com/YJ6fnh

    Gruesse,
    Der Kellerautomat



  • Musst du nicht <initializer_list> einbinden? (s. N3337, §8.5.4 / 2)
    Eine initializer_list kann übrigens keine Referenzen halten.


  • Mod

    Kellerautomat schrieb:

    Wieso klappt Uniform Initialization fast ueberall, nur bei Member-Referenzen nicht?

    Diese Frage ist zu ungenau und enthält zuviele Annahmen, um sinnvoll beantwortet werden zu können.

    List-Initialisierung einer Referenz führt zur Erzeugung eines temporären Objektes aus der Liste. Die Referenz wird dann an das temporäre Objekt gebunden.

    int x=0;
    const int& a = x; assert( &x == &a );
    const int& b(x);  assert( &x == &b );
    const int& a{x};  assert( &x != &c );
    


  • Und ich dachte sie wollten die Initialisierung damit einheitlich und intuitiver gestallten. 🙄



  • Camper meint vermutlich diesen Punkt:

    n3376 § 8.5.4/3 schrieb:

    Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized,
    and the reference is bound to that temporary.

    Etwas weiter oben in der Aufzählung (und damit zuerst zu berücksichtigen) ist das hier:

    n3376 § 8.5.4/3 schrieb:

    Otherwise, if the initializer list has a single element of type E and either T is not a reference type or
    its referenced type is reference-related to E, the object or reference is initialized from that element

    Weil foo& und foo& reference-related sind (8.5.3/4) entspricht das einer ganz normalen Initialisierung und der Code von K11t ist korrekt. clang kompiliert ihn übrigens anstandslos.


  • Mod

    prvreg schrieb:

    Camper meint vermutlich diesen Punkt:

    n3376 § 8.5.4/3 schrieb:

    Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized,
    and the reference is bound to that temporary.

    Etwas weiter oben in der Aufzählung (und damit zuerst zu berücksichtigen) ist das hier:

    n3376 § 8.5.4/3 schrieb:

    Otherwise, if the initializer list has a single element of type E and either T is not a reference type or
    its referenced type is reference-related to E, the object or reference is initialized from that element

    Weil foo& und foo& reference-related sind (8.5.3/4) entspricht das einer ganz normalen Initialisierung und der Code von K11t ist korrekt. clang kompiliert ihn übrigens anstandslos.

    Das wäre dann ein Defekt im gegenwärtigen Standard. "Ready"-Status läuft ja darauf hinaus, dass diese Änderung im nächsten TR drin sein wird.


Anmelden zum Antworten