Topic: return values declared non-const


Author: abrahams@spam.motu.com (David Abrahams)
Date: 1998/11/20
Raw View
On 19 Nov 1998 16:34:19 GMT, "Alex Martelli" <martelli@cadlab.it>
wrote:

>
>David Abrahams wrote in message <3651cb64.614156300@news.motu.com>...
>    [snip]
>>struct X {
>>  void non_const_mem_fn();
>>  void operator=( const Y& );
>
>I am surprised this compiles, since Y is not declared at this
>point in your code; have you snipped a forward declaration
>of struct Y previous to this point?

Actually, I misquoted my own code when I posted. That line should have
been:

  void operator=( const X& );

Everything else in the post is as it should be. Please try answering
again in light of this correction. Also, please quote chapter and
verse from the standard, if possible.

Thanks,
Dave
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "John E. Potter" <jpotter@falcon.lhup.edu>
Date: 1998/11/20
Raw View
On 18 Nov 1998, David Abrahams wrote:

> I'm hoping there's a core language guru out there who can shed some
> light on this situation:

Not qualified, but here is the quote you want.  From CD2 since my IS
is elsewhere.

3.10 [basic.lvalue]
10 An lvalue for an object is necessary in order to modify the object
   except  that  an  rvalue  of class type can also be used to modify its
   referent under certain circumstances.   [Example:  a  member  function
   called for an object (_class.mfct_) can modify the object.  ]

> struct X {
>   void non_const_mem_fn();
>   void operator=( const Y& );
                          X    as noted in your correction
> };
> struct Y {
>   void non_const_mem_fn();
> };
>
> X getX();
> const X get_const_X();
> void useX( X& );
> Y getY();
>
> void main()
> {
>
>   useX( getX() );   // 1
>   getX().non_const_mem_fn();  // 2
>   get_const_X().non_const_mem_fn(); // 3
>   getX() = X();    // 4
>   getY() = Y();    // 5
> }
>
> Line 1 is an error, since you can't bind a non-const reference to a
> temporary. Fine.

Yes.

> My compiler doesn't complain about line 2, but complains about line 3.
> Isn't line 2 an error (if not where does the non-const 'this' pointer
> come from inside non_const_mem_fn)?

An rvalue is an rvalue is an rvalue, but it is not const.  We have
modifiable rvalues and unmodifiable rvalues just like modifiable
lvalues and unmodifiable lvalues.

>   If so, what part of the standard says so?

See above: 3.10/10

>   If not, can you explain why line 1 is but line 2 is not?

You can not bind a non-const reference to a temporary because it
is an rvalue; however, the compiler can bind a pointer to non-const
to a temporary and use it to call member functions.

> Consistent with line 2, my compiler doesn't complain about line 4
> (X::operator= is also a non-const member function).

> My compiler complains about line 5, however ("not an lvalue"). Is my
> compiler broken or is there some sense in which an implicitly
> generated copy assignment operator differs from an explicitly declared
> one?

Your compiler is using old pre-standard rules.  It is considering the
operator= as the global operator= which requires an lvalue.  The fact
that every class has an operator= member function was not in the ARM.
That allowed copy assignment by whatever rules the implementation
used.  The IS demands that the compiler generate X& operator=(X const&)
for you and thus line 5 is as well formed as line 4.

John

> P.S. Please, no references to M.E.C++, item 6!

OK ;-), but I must give Scott credit for explaining the above to me via
several e-mails until it finally took.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/11/20
Raw View
David Abrahams <abrahams@spam.motu.com> writes:

> I'm hoping there's a core language guru out there who can shed some
> light on this situation:
>
> struct X {
>   void non_const_mem_fn();
>   void operator=( const Y& );

You mean X ?

> };
>
> struct Y {
>   void non_const_mem_fn();
> };
>
> X getX();
> const X get_const_X();
> void useX( X& );
> Y getY();
>
> void main()
> {
>
>   useX( getX() );   // 1

ill-formed

>   getX().non_const_mem_fn();  // 2

ok

>   get_const_X().non_const_mem_fn(); // 3

ill-formed

>   getX() = X();    // 4
>   getY() = Y();    // 5

both ok, they are equivalent

> }

> Consistent with line 2, my compiler doesn't complain about line 4
> (X::operator= is also a non-const member function).

Correct, with the strange implication that you assign
an rvalue.

> My compiler complains about line 5, however ("not an lvalue"). Is my
> compiler broken

yes

> or is there some sense in which an implicitly
> generated copy assignment operator differs from an explicitly declared
> one?

The implicitly declared one differs from yours because the return
type is X&, not void.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Alex Martelli" <martelli@cadlab.it>
Date: 1998/11/19
Raw View
David Abrahams wrote in message <3651cb64.614156300@news.motu.com>...
    [snip]
>struct X {
>  void non_const_mem_fn();
>  void operator=( const Y& );

I am surprised this compiles, since Y is not declared at this
point in your code; have you snipped a forward declaration
of struct Y previous to this point?

>};
>struct Y {
>  void non_const_mem_fn();
>};
>
>X getX();
>const X get_const_X();
>void useX( X& );
>Y getY();
>
>void main()
>{
>  useX( getX() ); // 1
>  getX().non_const_mem_fn(); // 2
>  get_const_X().non_const_mem_fn(); // 3
>  getX() = X(); // 4
>  getY() = Y(); // 5
>}

    [snip]

>My compiler doesn't complain about line 2, but complains about line 3.
>Isn't line 2 an error (if not where does the non-const 'this' pointer
>come from inside non_const_mem_fn)?
>  If so, what part of the standard says so?
>  If not, can you explain why line 1 is but line 2 is not?

No, line 2 is not an error; the "this" _pointer_ "comes from" the
address of temporary -- note that it is a pointer, not a reference.

One _is_ allowed to call non-const member functions on
temporaries -- this is a separate issue from passing a temporary
to an argument declared as taking a non-const *reference*.

>Consistent with line 2, my compiler doesn't complain about line 4
>(X::operator= is also a non-const member function).

Fine...

>My compiler complains about line 5, however ("not an lvalue"). Is my
>compiler broken or is there some sense in which an implicitly
>generated copy assignment operator differs from an explicitly declared
>one?


I have no explanation for your compiler's complaints about
line 5, so, perhaps, it IS broken.  However, please note that
explicitly declared copy assignment operators have nothing
to do with the case, because there isn't any such in sight
in your code (the assignment operator you defined for X
takes a const reference to an _Y_, NOT an _X_, and thus
it is not the copy assignment operator).

I suspect the code you tested may be different from the one
you posted, given both this mention of explicitly declared
copy assignment operators, and the strangeness of that
non-copy assignment operator for X compiling before the
declaration of Y has been seen; in which case, depending
on what exactly are the differences, then your compiler may
NOT be broken (e.g., if the copy assignment operator you
defined for X took a non-const reference to its X arg, AND
the complaint was about line 4 rather than about line 5 -- too
much assumption to be made here for my tastes, though:-).


Alex



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: abrahams@spam.motu.com (David Abrahams)
Date: 1998/11/18
Raw View
Hi,

I'm hoping there's a core language guru out there who can shed some
light on this situation:

struct X {
  void non_const_mem_fn();
  void operator=( const Y& );
};

struct Y {
  void non_const_mem_fn();
};

X getX();
const X get_const_X();
void useX( X& );
Y getY();

void main()
{

  useX( getX() );   // 1
  getX().non_const_mem_fn();  // 2
  get_const_X().non_const_mem_fn(); // 3
  getX() = X();    // 4
  getY() = Y();    // 5
}

Line 1 is an error, since you can't bind a non-const reference to a
temporary. Fine.

My compiler doesn't complain about line 2, but complains about line 3.
Isn't line 2 an error (if not where does the non-const 'this' pointer
come from inside non_const_mem_fn)?
  If so, what part of the standard says so?
  If not, can you explain why line 1 is but line 2 is not?

Consistent with line 2, my compiler doesn't complain about line 4
(X::operator= is also a non-const member function).

My compiler complains about line 5, however ("not an lvalue"). Is my
compiler broken or is there some sense in which an implicitly
generated copy assignment operator differs from an explicitly declared
one?

-Dave

P.S. Please, no references to M.E.C++, item 6!
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]