About binding a const reference to a sub-object of a temporary

后端 未结 3 761
迷失自我
迷失自我 2020-11-27 17:35

With code like

#include 

struct P2d {
    double x, y;
    P2d(double x, double y) : x(x), y(y) {}
    ~P2d() { printf("Destructor called         


        
3条回答
  •  天命终不由人
    2020-11-27 18:20

    I would argue for a bug in g++, because, quoting draft N3242, §12.2/5:

    The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:

    So its lifetime must be extended, except when:

    A temporary bound to a reference member in a constructor’s ctor-initializer [..]

    A temporary bound to a reference parameter in a function call [..]

    The lifetime of a temporary bound to the returned value in a function return statement [..]

    A temporary bound to a reference in a new-initializer [..]

    Our case doesn't fit any of these exceptions, thus it must follow the rule. I'd say g++ is wrong here.

    Then, regarding the quote aschepler brought up from the same draft §8.5.3/5 (emphasis mine):

    A reference to type "cv1 T1" is initialized by an expression of type "cv2 T2" as follows:

    1. If the reference is an lvalue reference and the initializer expression

      a. is an lvalue (but is not a bit-field) and "cv1 T1" is reference-compatible with "cv2 T2", or

      b. has a class type ...

      then ...

    2. Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.

      a. If the initializer expression

      • i. is an xvalue, class prvalue, array prvalue or function lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or

      • ii. has a class type ...

      then the reference is bound to the value of the initializer expression in the first case....

      b. Otherwise, a temporary of type "cv1 T1" is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). The reference is then bound to the temporary.

    Looking at what an xvalue is, this time quoting http://en.cppreference.com/w/cpp/language/value_category ...

    An xvalue ("expiring value") expression is [..]

    a.m, the member of object expression, where a is an rvalue and m is a non-static data member of non-reference type;

    ... the expression center().x should be an xvalue, thus case 2a from §8.5.3/5 applies (and not the copy). I'll stay with my suggestion: g++ is wrong.

提交回复
热议问题