Topic: Binding refs to temporaries etc.. (Was: Printing part of a string)


Author: gurnec@my-dejanews.com
Date: 1998/09/29
Raw View
Christopher Eltschka wrote in message
<360A3A1D.8F27C286@physik.tu-muenchen.de>...
>Valentin Bonnard wrote:
>>
>> I know it has been beaten to death, but what about the
>> following:
>>
>> - binding to the result of an implicit conversion is illegal
>> - binding to any other rvalue is ok

<clip>

>What about:
>
>    foo(1L);         // no conversion needed, since type matches
>    foo(long_var++); // dito
>
>    void bar(int&);
>    bar(1);          // again, no conversion needed


I agree, but this is solved easily enough.  Only allow this type of
binding on class types.  More specifically,

(definition: a reference-compatible type is one that could potentially be
*directly* bound to the reference in question; not exactly right, but
close enough)

A reference-compatible rvalue can be directly bound to a non-const
reference only if it is of class type.

This would have the nice symmetry that Valentin Bonnard mentioned:
rvalues of class type would be modifialbe through non-const member
funcions and also by functions taking non-const references, however
non-class type rvalues would remain non-modifiable.

This modification would have the same potential awkwardness that calling
non-const member functions on rvalues currently has:

class MyComplex;

void square_it(MyComplex& toBeSquared);

. . .

void foo() {
// doesn't make much sense, but possible:
  MyComplex().square_me();

// also makes little sense, and/but currently illegal:
  square_it(MyComplex());
}

NEW (related) SUBJECT, valarray defect:

All this talk of references reminds me of a defect in the standard
regarding valarray's assignment operators and constructors.  The change
above suggests a simple way to fix it.  First, a little review:

One of valarray's operator[]'s returns a slice_array rvalue.  Since
slice_array has reference semantics to the valarray, it declares a
private copy ctor to prevent copying.  It was the intent to allow
passing this return value to another valarray's ctor, which takes the
type const slice_array&.  Here is the problem:

The standard says that when a reference-compatible rvalue of class type
is bound to a const reference, it can either be directly bound or a new
temporary can be created.  Because a temporary MIGHT be created, the
copy ctor must be visible.  However, slice_array's copy ctor is
intentionally hidden.  Therefore, it can never be passed to valarray's
ctor (or its assignment operator).  This is also true of gslice_array's,
mask_array's, and indirect_array's.

With the change described by Valentin Bonnard, the solution is simple:
change valaray's ctors and assignment operators to take non-const
references.  A direct binding is then required and the *_array's copy
ctor need not be visible.

A related question:
Why is a temporary allowed in the case of binding a reference-compatible
rvalue of class type to a const reference?  Why not just require a
direct binding?

-Chris Gurnee

Just for reference, relevant clauses in the standard:
Valarray: 26.3.2.1 and 26.3.2.2
References: 8.5.3

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum


[ 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: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/09/24
Raw View
Valentin Bonnard wrote:
>
> I know it has been beaten to death, but what about the
> following:
>
> - binding to the result of an implicit conversion is illegal
> - binding to any other rvalue is ok
>
> Advantages:

[...]

> - it still catches the errors I want to catch:
>
>   void foo (long&);
>   foo (1);

What about:

    foo(1L);         // no conversion needed, since type matches
    foo(long_var++); // dito

    void bar(int&);
    bar(1);          // again, no conversion needed
---
[ 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/09/22
Raw View
I know it has been beaten to death, but what about the
following:

- binding to the result of an implicit conversion is illegal
- binding to any other rvalue is ok

Advantages:

- it allows obviously correct cases like

Siemel Naran wrote:
> On 18 Sep 1998 19:51:17 GMT, David Harmon <source@netcom.com> wrote:
> >On 17 Sep 1998 20:40:57 GMT, sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
>
> >>>     string first, middle, last;
> >>>     stringstream(name) >> first >> middle >> last;

- it still catches the errors I want to catch:

  void foo (long&);
  foo (1);

- it would restore the equivalence between implicit and explicit
  function arguments:

  struct foo {
      foo& operator<< (int);
      foo (bar);
  };
  foo& operator<< (foo&, long);

  foo () << 3 << 3L; // legal now, still legal
  foo () << 3L << 3; // illegal now, would be legal

  bar () << 3L; // illegal, no convertion allowed on implicit
                // this argument
  bar () << 3;  // illegal, can't bind to ...

Problems: ???

--

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              ]