Mutability of temporary variables

Discussion in 'C++' started by kyle, Nov 19, 2011.

  1. kyle

    kyle Guest

    Consider following code:

    int main() {
    const int& c = int();
    int& m = const_cast<int&>(c);
    m = 4;
    }

    The object of the snippet is to get a mutable reference to a temporary.
    This cant be done directly because non-const reference cannot bind to
    temporary, but we should be OK with casting away constness of reference
    'c' since it doesn't actually refer to const object.

    Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?

    --
    kyle
    kyle, Nov 19, 2011
    #1
    1. Advertising

  2. On 11/19/2011 7:33 AM, kyle wrote:
    > Consider following code:
    >
    > int main() {
    > const int& c = int();
    > int& m = const_cast<int&>(c);
    > m = 4;
    > }
    >
    > The object of the snippet is to get a mutable reference to a temporary.
    > This cant be done directly because non-const reference cannot bind to
    > temporary, but we should be OK with casting away constness of reference
    > 'c' since it doesn't actually refer to const object.
    >
    > Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?


    AIUI, your code has undefined behavior. 'c' is bound to an rvalue, and
    using 'const_cast' to produce an lvalue out of it is not among the
    allowed operations for 'const_cast'.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 19, 2011
    #2
    1. Advertising

  3. On 11/19/2011 8:18 AM, Paavo Helde wrote:
    > kyle<> wrote in
    > news:eek::
    >
    >> Consider following code:
    >>
    >> int main() {
    >> const int& c = int();
    >> int& m = const_cast<int&>(c);
    >> m = 4;
    >> }
    >>
    >> The object of the snippet is to get a mutable reference to a
    >> temporary. This cant be done directly because non-const reference
    >> cannot bind to temporary, but we should be OK with casting away
    >> constness of reference 'c' since it doesn't actually refer to const
    >> object.
    >>
    >> Temporaries are mutable, so in whole my snippet is legal C++. Am i
    >> correct?

    >
    > Yes, I think you are correct. Another trick to get a mutable reference to
    > a temporary is to use a non-const member function. This avoids
    > const_cast, but of course lifetime extending by binding to a const
    > reference does not work any more:
    >
    > struct A {
    > int m;
    > A& Ref() {return *this;}
    > };
    >
    > void f(A& a) {
    > a.m = 4;
    > }
    >
    > int main() {
    > f( A().Ref() );
    > }
    >


    There is a difference between your example and the OP's. In your
    example the temporary is of a class type, and the expression A()
    produces an lvalue to begin with.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 19, 2011
    #3
  4. kyle wrote:

    > Consider following code:
    >
    > int main() {
    > const int& c = int();
    > int& m = const_cast<int&>(c);
    > m = 4;
    > }
    >
    > The object of the snippet is to get a mutable reference to a temporary.
    > This cant be done directly because non-const reference cannot bind to
    > temporary, but we should be OK with casting away constness of reference
    > 'c' since it doesn't actually refer to const object.
    >


    The error in your thinking is that you think that "int()" is a temporary
    object.

    However, "int()" is not a temporary object. It is simply a value, and when
    it is an initializer of a reference, a temporary object will be initialized
    with that value, and the object will have the type and constness of the
    referred type of the reference.

    So in your case the reference refers to an object of type "const int" - you
    are not allowed to modify it.
    Johannes Schaub, Nov 19, 2011
    #4
  5. On 11/19/2011 9:20 AM, Paavo Helde wrote:
    > Victor Bazarov<> wrote in
    > news:ja8bo7$88k$:
    >
    >> On 11/19/2011 7:33 AM, kyle wrote:
    >>> Consider following code:
    >>>
    >>> int main() {
    >>> const int& c = int();
    >>> int& m = const_cast<int&>(c);
    >>> m = 4;
    >>> }
    >>>
    >>> The object of the snippet is to get a mutable reference to a
    >>> temporary. This cant be done directly because non-const reference
    >>> cannot bind to temporary, but we should be OK with casting away
    >>> constness of reference 'c' since it doesn't actually refer to const
    >>> object.
    >>>
    >>> Temporaries are mutable, so in whole my snippet is legal C++. Am i
    >>> correct?

    >>
    >> AIUI, your code has undefined behavior. 'c' is bound to an rvalue,
    >> and using 'const_cast' to produce an lvalue out of it is not among the
    >> allowed operations for 'const_cast'.

    >
    > The lvalue and rvalue notions apply to source code expressions (3.10/1:
    > "Every expression is either an lvalue or an rvalue"). Expression 'c' is
    > of a reference type, which means it is a lvalue, doesn't it? (rvalue
    > references use&& syntax). And lvalue->lvalue conversion is well defined
    > for const_cast.
    >
    > Or have I misunderstood something?


    int() is an rvalue expression. Now, explain that.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 19, 2011
    #5
  6. kyle

    SG Guest

    On Nov 19, 2:45 pm, Victor Bazarov wrote:

    > There is a difference between your example and the OP's.  In your
    > example the temporary is of a class type, and the expression A()
    > produces an lvalue to begin with.


    You seem to confuse two concepts, (1) value category and (2) whether
    or not an expression refers to an object. There is some correlation
    between these two but no equivalence. What is true though is that
    every lvalue (of object type) refers to an object. But T() is always
    an rvalue expression no matter what kind of object type T is (scalar
    or not). Let me quote part of 3.10 of the current C++ ISO standard:

    "An rvalue (...) is an xvalue, a temporary object or a subobject
    thereof, or a value that is not associated with an object."

    So, saying that A() is an rvalue which refers to a temporary object is
    not a contradiction.

    In the former version of the standard it was also clarified when an
    rvalue (that is not an xvalue) actually refers to an object and when
    not. I can't find it in the current incarnation but I guess it did not
    change. PRvalues of _scalar_types_ are not associated with an object,
    they are just "values". And since int is a scalar type int() does not
    refer to an object (temporary or otherwise). But of course, a
    reference of object type has to refer to an object. That's why a
    temporary object is created as part of the reference initialization
    procedure.

    I suggest to look up §3.10 and the part about reference initialization
    in both versions of the C++ ISO standard.

    Cheers!
    SG
    SG, Nov 20, 2011
    #6
  7. kyle

    SG Guest

    On Nov 19, 1:33 pm, kyle wrote:
    >
    > int main() {
    >    const int& c = int();
    >    int& m = const_cast<int&>(c);
    >    m = 4;
    > }
    >
    > [...]
    >
    > Temporaries are mutable, so in whole my snippet is legal C++. Am i correct?


    Yes, I believe so. I would not go as far as saying "temporaries are
    mutable" because one can easily create const class-type temporaries.
    These are obviously not mutable unless they have mutable data members.
    But, I agree with Paavo on this one. As far as I can tell, no
    undefined behaviour is invoked here.

    Cheers!
    SG
    SG, Nov 21, 2011
    #7
  8. SG wrote:

    > On Nov 19, 1:33 pm, kyle wrote:
    >>
    >> int main() {
    >> const int& c = int();
    >> int& m = const_cast<int&>(c);
    >> m = 4;
    >> }
    >>
    >> [...]
    >>
    >> Temporaries are mutable, so in whole my snippet is legal C++. Am i
    >> correct?

    >
    > Yes, I believe so. I would not go as far as saying "temporaries are
    > mutable" because one can easily create const class-type temporaries.
    > These are obviously not mutable unless they have mutable data members.
    > But, I agree with Paavo on this one. As far as I can tell, no
    > undefined behaviour is invoked here.
    >


    What do you say about the point I have made about the code?
    Johannes Schaub, Nov 22, 2011
    #8
  9. kyle

    kyle Guest

    Dnia 19-11-2011 o 16:16:45 Johannes Schaub
    <> napisał(a):

    > kyle wrote:
    >
    >> Consider following code:
    >>
    >> int main() {
    >> const int& c = int();
    >> int& m = const_cast<int&>(c);
    >> m = 4;
    >> }
    >>

    >
    > The error in your thinking is that you think that "int()" is a temporary
    > object.
    >


    This is indeed what i assumed.
    As i understand, i could 'fix' the code by having a function 'int foo()
    {return 1;}' and using it in place of 'int()'?

    Unfortunately, what i originally planned to do is illegal for entirely
    different reason ;)

    --
    kyle
    kyle, Nov 23, 2011
    #9
  10. kyle wrote:

    > Dnia 19-11-2011 o 16:16:45 Johannes Schaub
    > <> napisał(a):
    >
    >> kyle wrote:
    >>
    >>> Consider following code:
    >>>
    >>> int main() {
    >>> const int& c = int();
    >>> int& m = const_cast<int&>(c);
    >>> m = 4;
    >>> }
    >>>

    >>
    >> The error in your thinking is that you think that "int()" is a temporary
    >> object.
    >>

    >
    > This is indeed what i assumed.
    > As i understand, i could 'fix' the code by having a function 'int foo()
    > {return 1;}' and using it in place of 'int()'?
    >


    No, as someone else already said, rvalues of non-class and non-array type
    are not objects, and the rules for initialization of references adequately
    are worded to take that into account. It will behave exactly like the
    "int()" case.
    Johannes Schaub, Nov 24, 2011
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Edward C. Jones

    Mutability problem when subclassing tuple

    Edward C. Jones, Feb 19, 2004, in forum: Python
    Replies:
    2
    Views:
    580
    Shalabh Chaturvedi
    Feb 19, 2004
  2. ex_ottoyuhr

    Mutability of function arguments?

    ex_ottoyuhr, Dec 8, 2005, in forum: Python
    Replies:
    17
    Views:
    452
    Fredrik Lundh
    Dec 8, 2005
  3. gigs

    list mutability

    gigs, Feb 18, 2008, in forum: Python
    Replies:
    1
    Views:
    222
    John Machin
    Feb 18, 2008
  4. named tuple mutability

    , May 14, 2008, in forum: Python
    Replies:
    10
    Views:
    437
    Bruno Desthuilliers
    May 15, 2008
  5. cnb
    Replies:
    1
    Views:
    202
    Alan G Isaac
    Aug 26, 2008
Loading...

Share This Page