Topic: Binding temp rvalue to const volatile reference


Author: thp@cs.ucr.edu
Date: Thu, 19 Jul 2001 19:00:43 GMT
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
: In article <9icuoe$m9b$1@bcarh8ab.ca.nortel.com>, Gary Mussar
: <mussar@nortelnetworks.com> writes
:>I am still confused with how const volatile references are different from
:>const references in the "spirit of the standard". I must be missing
:>something subtle (or maybe not so subtle).

: Because const volatile things are not immutable, they just cannot be
: changed here. Now as we are talking about temporaries, what does it mean
: to have a volatile temporary?

Good question.  I guess, by definition, a volatile temporary is a
place to store a voltile rvalue.  But that simply rasise the
questions: what's a volatile rvalue?  (I think of volatility as an
attribute of objects, i.e., lvalues.)

Tom Payne

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Tue, 17 Jul 2001 01:25:25 GMT
Raw View
"Gary Mussar" <mussar@nortelnetworks.com> wrote in message
news:9iurng$asu$1@bcarh8ab.ca.nortel.com...
>
> I understand to problems associated with binding temporaries to references
> that allow modification. (Yes, I have spent a fair amount of time tracking
> this down and was most annoyed when I found that the original developer
had
> ignored the g++ compiler warning about this.)
>
> But I am not talking about binding a temporary to a non-const type
reference
> that would allow the temporary to be changed. A const volatile reference
is
> just as read-only as a const reference. C++ will not allow a const
volatile
> reference to be used to change the object.

AFAIK under the current rules, the compiler is free to assume that nothing
is changing the value attached to a const& "behind-the-scenes", and can,
e.g., keep it in a register as the compiler can deduce that nothing within
the called function is modifying the value. A volatile qualification is used
to tell the compiler that the value may change out from underneath it (e.g.
by some pre-emptive thread), and so must re-load it from memory whenever it
is accessed.

It seems apparent to me that binding a volatile object to a non-volatile
reference is not something that should happen silently.

-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://www.research.att.com/~austern/csc/faq.html                ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Tue, 17 Jul 2001 20:31:27 GMT
Raw View
Howard Hinnant <hinnant@antispam.twcny.rr.com> wrote in message news:<140720012301308566%hinnant@antispam.twcny.rr.com>...
> In article <memo.20010714201144.2069C@brangdon.madasafish.com>, Dave
> Harris <brangdon@cix.co.uk> wrote:
>
> | hinnant@antispam.twcny.rr.com (Howard Hinnant) wrote (abridged):
> | > In the best of all languages, I would be able to specify that a
> | > non-const reference bind to a temporary or not (with a default of not).
> |
> | Would you be happy with the proposal that the binding be allowed if and
> | only if no implicit conversions are needed? Eg:
> |
> |     float &a = 1.0f; // OK.
> |     float &b = 1.0; // Compile error.
> |     float &c = 1; // Compile error.
> |     float &d = float(1); // OK.
> |
> | This is one of the three language changes that I would strongly like to
> | see in the next standard.
>
> That's an interesting compromise.  However I'm not sure I completely
> follow the logic.
>
> The logic of not binding a reference to a temporary follows from:  a
> reference argument is used for outputting information (and maybe
> inputting as well).  If you don't want to output information via an
> argument, then that argument should be const.  And if the argument is a
> temporary, then by definition it can not be used to output information.
> Therefore temporaries should not bind to non-const referenece.
[...]

Forwarding functions? I don't know whether I want to output
information or not, I need to pass arguments unmodified to someone
else.

IOW

template<class T> void f(T & t)
{
  g(t);
}

--
Peter Dimov
Multi Media Ltd.

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Tue, 17 Jul 2001 22:40:49 GMT
Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message
news:9ivssd$mic$1@bob.news.rcn.net...
> AFAIK under the current rules, the compiler is free to assume that nothing
> is changing the value attached to a const& "behind-the-scenes", and can,
> e.g., keep it in a register as the compiler can deduce that nothing within
> the called function is modifying the value. A volatile qualification is
used
> to tell the compiler that the value may change out from underneath it
(e.g.
> by some pre-emptive thread), and so must re-load it from memory whenever
it
> is accessed.
>
> It seems apparent to me that binding a volatile object to a non-volatile
> reference is not something that should happen silently.


All true. But I was not talking about binding a volatile to a non-volatile
reference. I am talking about the current restriction where a temporary
(plain, const, or volatile) cannot be bound to a const volatile reference
during parameter passing. The parameter cannot be used to change the bound
object since a const volatile reference is just as read-only as binding to a
const reference parameter. The additional volatile specifier means the
compiler should be very careful about reading and caching values from the
object.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Fri, 13 Jul 2001 17:05:42 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:Fk7U1RBkIXT7Ew$q@ntlworld.com...
> In article <9iis37$dbm$1@bcarh8ab.ca.nortel.com>, Gary Mussar
> <mussar@nortelnetworks.com> writes
> >I still don't understand what subtle, yet dangerous differences there are
> >between const reference parameters and volatile const references
parameters
> >that lead to the restriction on binding rvalue temporaries to volatile
const
> >reference parameters in the standard.
>
> The concept was simply that a a temporary bound to a reference should be
> immutable by any means. Volatile qualification announces that this is
> not the case. That was fine till we introduced mutable, which now meant
> that in some circumstances attempting to change a const qualified
> instance was no longer undefined behaviour.

In "Design and Evolution of C++", Stroustrup talks briefly about volatile.
He said the volatile specifier was added to match ANSI C and ANSI C added it
to help optimizer implementers. He seems to have had some doubts about the
syntactic parallel with the const specifier but had no strong feelings about
volatile. This is unfortunate.

Let's consider the original const specifier (before the mutable keyword
muddled things up). I assume the argument that a const object should mean
that the object is immutable by any means. Binding any (const or non-const)
object to a const reference should mean that the reference cannot be used to
change the original object. This does not mean that the object itself cannot
be changed but only that it cannot be changed via the const reference. Of
course aliasing with any kind of reference will invoke undefined behaviour.

The volatile specifier can be combined with the const specifier. In as far
as const should have meant immutable by any means, const volatile means that
the object is not modifiable via the object identifier but something may
change the object in unknown ways. I don't really see any philisophical
difference between this and a const reference bound to a non-const object.
This is better in some ways because we have acknowledged that the object may
change in unknown ways to aid the optimizer implementer and we don't have
the reference aliasing problem. I don't see that adding the volatile
specifier to a const object should ever allow translated code to change the
object. This should still invoke a compile time diagnostic.

Similarly, binding a temporary to a const volatile reference should never
allow any code using that reference to change the temporary. The additional
volatile specifier should only be a concern to the optimizer implementers. A
const reference parameter indicates that the function cannot change the
non-value parameter. A const volatile reference parameter indicates that the
function cannot change the non-value parameter and that the optimizer will
be very careful about accesses to the object. The additional volatile
specifier does not allow any additional capabilities to access the object
(in fact it makes it more restrictive).

The fact that something unknown, some where might be able to change the
value of a const volatile object (or the object referred to by a const
volatile reference) is beyond the scope of the const volatile object or an
interface employing a const volatile reference.

> Again the theory was that all this was largely to support non-value
> parameters and that you would (should?) not want to alter something that
> is about to go away. Fine, but we blew that one when we allowed member
> functions to be called on a temporary.

The mutable keyword which allows portions of const objects to be non-const
and the ability to invoke non-const member functions on a temporary make the
restriction on binding temporaries to const volatile references seem silly.
More over, it seems inconsistent to me and perhaps a bit irrational. Am I
the only one to see it that way?

Gary




---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Howard Hinnant <hinnant@antispam.twcny.rr.com>
Date: Fri, 13 Jul 2001 19:35:14 GMT
Raw View
In article <9in5bk$bhe$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> wrote:

| The mutable keyword which allows portions of const objects to be non-const
| and the ability to invoke non-const member functions on a temporary make the
| restriction on binding temporaries to const volatile references seem silly.
| More over, it seems inconsistent to me and perhaps a bit irrational. Am I
| the only one to see it that way?

Years ago, using an older compiler of course, I (mistakenly) wrote code
that passed a float to a function expecting a double&, with the intent
that the function was supposed to modify the double as a result.

The compiler dutifully created a temporary double, bound it to the
non-const reference, and let me modify it in the function.  This was in
a fairly large and complicated scientific/engineering application.  It
took me forever to track down that bug!

Since then I have very much appreciated the ban on binding a temporary
to a non-const referenece.  That being said, sometimes I /do/ want to
bind a temporary to a non-const reference.  There are valid reasons why
you might want to modify a temporary within a function.  For example
you might want to transfer resources from the temporary to another
object:

T build_a_T();

T t1;
t.get_resources_from(build_a_T());

In the best of all languages, I would be able to specify that a
non-const reference bind to a temporary or not (with a default of not).

--
Howard Hinnant

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Sat, 14 Jul 2001 23:30:39 GMT
Raw View
hinnant@antispam.twcny.rr.com (Howard Hinnant) wrote (abridged):
> In the best of all languages, I would be able to specify that a
> non-const reference bind to a temporary or not (with a default of not).

Would you be happy with the proposal that the binding be allowed if and
only if no implicit conversions are needed? Eg:

    float &a = 1.0f; // OK.
    float &b = 1.0; // Compile error.
    float &c = 1; // Compile error.
    float &d = float(1); // OK.

This is one of the three language changes that I would strongly like to
see in the next standard.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Howard Hinnant <hinnant@antispam.twcny.rr.com>
Date: Mon, 16 Jul 2001 17:02:31 GMT
Raw View
In article <memo.20010714201144.2069C@brangdon.madasafish.com>, Dave
Harris <brangdon@cix.co.uk> wrote:

| hinnant@antispam.twcny.rr.com (Howard Hinnant) wrote (abridged):
| > In the best of all languages, I would be able to specify that a
| > non-const reference bind to a temporary or not (with a default of not).
|
| Would you be happy with the proposal that the binding be allowed if and
| only if no implicit conversions are needed? Eg:
|
|     float &a = 1.0f; // OK.
|     float &b = 1.0; // Compile error.
|     float &c = 1; // Compile error.
|     float &d = float(1); // OK.
|
| This is one of the three language changes that I would strongly like to
| see in the next standard.

That's an interesting compromise.  However I'm not sure I completely
follow the logic.

The logic of not binding a reference to a temporary follows from:  a
reference argument is used for outputting information (and maybe
inputting as well).  If you don't want to output information via an
argument, then that argument should be const.  And if the argument is a
temporary, then by definition it can not be used to output information.
Therefore temporaries should not bind to non-const referenece.

However this logic fails when you realize that there may be situations
where the output of a function may depend on non-const operations of an
argument, the output is not via the arg, and that any changes to the
non-const ref arg are not considered output of the function.  Said
another way:  I want to destructively extract information from the
argument.  The final value of the argument is immaterial.

While you're proposal looks like a step in the right direction, I'm not
seeing how conversions that create the temporary effect the logic I've
outlined.  How does it matter how the temporary was created?  You still
want to modify it.  And you still don't care what value it contains at
function's end.

I would rather see something like:

float temp& = 1.0;  // ok, binds to temporary

However I would be very nervous about classifying "temp" as another cv
qualifier.  Indeed, I believe it is not.  Instead I merely want syntax
to say:  this reference can bind to a non-const T, or a temporary T,
but not a const T.

We may actually have something getting close to this.  Consider:

template <class T>
class move_t
{
public:
    explicit move_t(T& a) : ptr_(&a) {}
private:
   T* ptr_;
};

template <class T>
move_t<T>
move(T t)
{
   return move_t<T>(t);
}

template <class T>
move_t<T>
move(T& t)
{
   return move_t<T>(t);
}

template <class T>
T
source()
{
   return T();
}

struct A {/* ... */};

int main()
{
   A i;
   A i2(move(i));
   A i3(move(source<A>()));
}

The intent is that move(source<A>()) will bind to move(A), while
move(i) will bind to move(A&).

14.5.5.2/5 explicitly says that move(i) should be ambiguous.  However
cwg open issue 214
(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214)
disputes this and says it is not ambiguous.  Should the ruling come
down in favor of 214, then we may have an existing method of "binding"
a temporary T to a non-const reference, though at the cost of a
hopefully elided copy construction.

However, all of this feels like a lot of dancing around to achieve the
desired effect (and limited to template functions, not ordinary
functions), when I would really like to state it more directly as
something like:

template <class T>
move_t<T>
move(T temp& t)  // bind to T, even if temporary
{
   return move_t<T>(t);
}

--
Howard Hinnant

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Mon, 16 Jul 2001 17:16:38 GMT
Raw View
"Howard Hinnant" <hinnant@antispam.twcny.rr.com> wrote in message
news:130720011431220720%hinnant@antispam.twcny.rr.com...
> In article <9in5bk$bhe$1@bcarh8ab.ca.nortel.com>, Gary Mussar
> <mussar@nortelnetworks.com> wrote:
>
> | The mutable keyword which allows portions of const objects to be
non-const
> | and the ability to invoke non-const member functions on a temporary make
the
> | restriction on binding temporaries to const volatile references seem
silly.
> | More over, it seems inconsistent to me and perhaps a bit irrational. Am
I
> | the only one to see it that way?
>
> Years ago, using an older compiler of course, I (mistakenly) wrote code
> that passed a float to a function expecting a double&, with the intent
> that the function was supposed to modify the double as a result.
>
> The compiler dutifully created a temporary double, bound it to the
> non-const reference, and let me modify it in the function.  This was in
> a fairly large and complicated scientific/engineering application.  It
> took me forever to track down that bug!

I understand to problems associated with binding temporaries to references
that allow modification. (Yes, I have spent a fair amount of time tracking
this down and was most annoyed when I found that the original developer had
ignored the g++ compiler warning about this.)

But I am not talking about binding a temporary to a non-const type reference
that would allow the temporary to be changed. A const volatile reference is
just as read-only as a const reference. C++ will not allow a const volatile
reference to be used to change the object.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl>
Date: Mon, 16 Jul 2001 18:25:33 GMT
Raw View
Mon, 16 Jul 2001 17:02:31 GMT, Howard Hinnant <hinnant@antispam.twcny.rr.=
com> pisze:

> While you're proposal looks like a step in the right direction, I'm not
> seeing how conversions that create the temporary effect the logic I've
> outlined.

If an lvalue is being implicitly converted, it looks like the specified
object was being modified, but in reality it's not. Introducing
an implicit conversion changes the meaning completely - object
identity was important, not only value, and this doesn't play well
with implicit conversions which might more or less preserve the value
but will definitely change the identity.

--=20
 __("<  Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
 \__/
  ^^                      SYGNATURA ZAST=CAPCZA
QRCZAK

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Mon, 9 Jul 2001 22:50:50 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:Jz5nQZCq2gS7EwHI@ntlworld.com...
> In article <9icuoe$m9b$1@bcarh8ab.ca.nortel.com>, Gary Mussar
> <mussar@nortelnetworks.com> writes
> >I am still confused with how const volatile references are different from
> >const references in the "spirit of the standard". I must be missing
> >something subtle (or maybe not so subtle).
>
> Because const volatile things are not immutable, they just cannot be
> changed here.

I suppose you can argue that the only reason to use the volatile specifier
is "because the value of the object might be changed by means undetectable
by an implementation". This doesn't mean that any code in the system is
changing this value. It could just as easily represent hardware control and
status registers (as it does in our system). You can easily have a piece of
hardware that is read-only (generates traps if attempts are made to write
it), but changes value (like a real-time counter).

> Now as we are talking about temporaries, what does it mean
> to have a volatile temporary?

I wasn't talking about having a const volatile temporary. I was looking at a
set of assignment operators for a class that has both non-volatile and
volatile instances. I could generate 4 different assignment operators to
cover all the nonvolatile-volatile cases.

eg.
class X
{
   ...
   // Assignment to volatile from non-volatile
   volatile X & operator=(const X &) volatile;

   // Assignment to volatile from volatile
   volatile X & operator=(const volatile X &) volatile;

   // Assignment to non-volatile from non-volatile
   X & operator=(const X &);

   // Assignment to non-volatile from volatile
   X & operator=(const volatile X &);
};

If I omit the versions with const volatile references, then I cannot assign
from volatile object since this is discarding the volatile specifier of the
source object.

If I omit the versions with const references, I cannot assign from any
rvalue that are not const volatile (which is most rvalues).

Defining all 4 seems to be quite a waste. It would be more palatable if I
had a good argument why binding temporaries (non-volatile or const) to const
volatile references was so dangerous as to be explicitly outlawed by the
standard.

There are trade-offs between code complexity (increased lines of code, more
methods, etc.) and the inefficiencies in dealing with volatile objects but
the standard has removed that decision from the developer.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Wed, 11 Jul 2001 17:00:15 GMT
Raw View
In article <9idbud$d7j$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> writes
>class X
>{
>   ...
>   // Assignment to volatile from non-volatile
>   volatile X & operator=(const X &) volatile;
>
>   // Assignment to volatile from volatile
>   volatile X & operator=(const volatile X &) volatile;
>
>   // Assignment to non-volatile from non-volatile
>   X & operator=(const X &);
>
>   // Assignment to non-volatile from volatile
>   X & operator=(const volatile X &);
>};

Yes, but the trouble is that the argument being bound to the reference
parameter might be a temporary, and so you need all four.


Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Wed, 11 Jul 2001 20:14:10 CST
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:UnuglIA3PkS7Ewlw@ntlworld.com...
> In article <9idbud$d7j$1@bcarh8ab.ca.nortel.com>, Gary Mussar
> <mussar@nortelnetworks.com> writes
> >class X
> >{
> >   ...
> >   // Assignment to volatile from non-volatile
> >   volatile X & operator=(const X &) volatile;
> >
> >   // Assignment to volatile from volatile
> >   volatile X & operator=(const volatile X &) volatile;
> >
> >   // Assignment to non-volatile from non-volatile
> >   X & operator=(const X &);
> >
> >   // Assignment to non-volatile from volatile
> >   X & operator=(const volatile X &);
> >};
>
> Yes, but the trouble is that the argument being bound to the reference
> parameter might be a temporary, and so you need all four.

I do understand that the current wording in the standard means that I will
need all four versions of the assignment operator.

I still don't understand what subtle, yet dangerous differences there are
between const reference parameters and volatile const references parameters
that lead to the restriction on binding rvalue temporaries to volatile const
reference parameters in the standard.

I'm not questioning the interpretation of the words in the current standard.
I'm trying to understand the rationale for excluding the binding of rvalues
to volatile const references while allowing them to bind to const reference
parameters. Am I missing a subtle, yet dangerous difference? Is the current
standard overly conservative? Is this something that the committee never
considered before?  Is there a possibility that this could be relax in the
next version of the standard assuming there really isn't a significant
danger?

I would like to create some guidelines for our developers on when it may be
appropriate or necessary to employ the volatile specifier. I would also like
to provide guidelines on how to create a class that can have volatile and
non-volatile instances. I can easily explain the need for two assignment
operators since the assignment operator that updates a volatile destination
should return a reference to a volatile instance of the class. I have no
explanation why you need four different assignment operators other than this
being an oversight in the standard or a deliberate bias to make the use of
volatile objects as painful (and error prone) as possible. Perhaps this is
the correct explanation.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Thu, 12 Jul 2001 13:08:54 GMT
Raw View
In article <9iis37$dbm$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> writes
>I still don't understand what subtle, yet dangerous differences there are
>between const reference parameters and volatile const references parameters
>that lead to the restriction on binding rvalue temporaries to volatile const
>reference parameters in the standard.


The concept was simply that a a temporary bound to a reference should be
immutable by any means. Volatile qualification announces that this is
not the case. That was fine till we introduced mutable, which now meant
that in some circumstances attempting to change a const qualified
instance was no longer undefined behaviour.

Again the theory was that all this was largely to support non-value
parameters and that you would (should?) not want to alter something that
is about to go away. Fine, but we blew that one when we allowed member
functions to be called on a temporary.

I think the chance of it being relaxed in the next C++ Standard is
small, because there is an entrenched sub-cummunity that spits blood at
such relaxations. My guess is that the C++ Standards Committees would be
unable to get near consensus on this issue -- but I could be wrong.

Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Fri, 6 Jul 2001 17:56:43 GMT
Raw View
In article <9i31fh$s3h$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> writes
>The standard states that a temporary that is an rvalue cannot be bound to a
>non-const reference for parameter passing. There are 4 possible cv qualified
>types for class T: T, const T, volatile T and const volatile T. Is a const
>volatile reference considered a const reference or a non-const reference?
>The GNU compiler certainly treats a const volatile reference parameter as a
>non-const reference and issues a diagnostic.

I am pretty certain that within the terms of the standard const volatile
references can be bound to temporaries. However I have every sympathy
with a compiler that issues a diagnostic because writing such code
breaches the spirit if not the letter of the Standard.

Furthermore I think this is a purely academic issue because I think any
attempt to write such code would be a breach of sound design.

Rather subtler would be something like this:

class X {
  mutable int i;
public:
  X():i(0) {}
  int & foo() const;
};

X const bar(){X x; return x;}

int main(){
  X const & x_ref = bar();
  x_ref.foo = 1;
  return 0;
}

Definitely, IMO, breaches the spirit but certainly within the letter.


Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Fri, 6 Jul 2001 17:56:50 GMT
Raw View
"Gary Mussar" <mussar@nortelnetworks.com> wrote in message
news:9i31fh$s3h$1@bcarh8ab.ca.nortel.com...
> The standard states that a temporary that is an rvalue cannot be bound to
a
> non-const reference for parameter passing. There are 4 possible cv
qualified
> types for class T: T, const T, volatile T and const volatile T. Is a const
> volatile reference considered a const reference or a non-const reference?
> The GNU compiler certainly treats a const volatile reference parameter as
a
> non-const reference and issues a diagnostic.
>
> I'm trying to determine whether this is a bug in g++, an ambiguity in the
> standard or my incomplete understanding of the standard. Any opinion would
> be appreciated.

The compiler is right:

8.5.3p5 (abbreviated):
"A reference to type "cv1 T1" is initialized by an expression of type "cv2
T2" as follows:
- If the initializer expression
* is an lvalue (but is not a bitfield), and "cv1 T1" is reference compatible
with "cv2 T2," or
* has a class type (i.e., T2 is a class type) and can be implicitly
converted to an lvalue of type "cv3 T3," where "cv1 T1" is reference
compatible with "cv3 T3",

then the reference is bound directly to the initializer expression lvalue in
the first case, and the reference is bound to the lvalue result of the
conversion in the second case.

-Otherwise, the reference shall be to a nonvolatile const type (i.e., cv1
shall be const)."

Temporaries are not lvalues, and can't convert to lvalues of any type unless
you provide an explicit conversion operator, so the "Otherwise" clause
applies, which specifies a non-volatile const reference. (Why non-volatile
is a good question)

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer



---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Sat, 7 Jul 2001 05:40:47 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message
news:9i44r3$gve5q$1@ID-49767.news.dfncis.de...
> The compiler is right:
>
> 8.5.3p5 (abbreviated):
> "A reference to type "cv1 T1" is initialized by an expression of type "cv2
> T2" as follows:
> - If the initializer expression
> * is an lvalue (but is not a bitfield), and "cv1 T1" is reference
compatible
> with "cv2 T2," or
> * has a class type (i.e., T2 is a class type) and can be implicitly
> converted to an lvalue of type "cv3 T3," where "cv1 T1" is reference
> compatible with "cv3 T3",
>
> then the reference is bound directly to the initializer expression lvalue
in
> the first case, and the reference is bound to the lvalue result of the
> conversion in the second case.
>
> -Otherwise, the reference shall be to a nonvolatile const type (i.e., cv1
> shall be const)."

Yup. That is what it says (now that I re-read this section a few times :-).
It really is a mystery to me why it explicitly states nonvolatile const type
for cv1 here. I don't understand how the addition of the volatile qualifier
to the reference parameter would make the design less safe (or sound). Its
not as if adding volatile makes the parameter mutable. Perhaps someone
remembers why this restriction exists in 8.5.3p5.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Sat, 7 Jul 2001 23:04:49 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:rUafpVAr3XR7EwIY@ntlworld.com...
> I am pretty certain that within the terms of the standard const volatile
> references can be bound to temporaries. However I have every sympathy
> with a compiler that issues a diagnostic because writing such code
> breaches the spirit if not the letter of the Standard.
>
> Furthermore I think this is a purely academic issue because I think any
> attempt to write such code would be a breach of sound design.

The developer has created a class and has both volatile and non-volatile
instances (embedded, multi-threaded application). I was helping them write
assignment operators for this class and I was trying to minimize the number
of assignment operators.

eg.

class X
{
   ...
public:
   volatile X & operator=(const volatile X &) volatile;
   X & operator=(const volatile X&);
   ...
};

I was hoping the first assignment operator would allow assignments to
volatile Xs from any kind of X (plain, const, volatile or const volatile)
and the 2nd one would allow assignments to non-volatile Xs from any kind of
X.

G++ will not allow the binding of a temporary rvalue in the assignment
operator because the parameter is not a simple const reference.

Is the breach of sound design "any use of volatile", use of a volatile
instance of a class or the attempt to minmimize the number of assignment
operators?

Should a class with volatile instances define 4 assignment operators to
cover all the possible assignments? Similarly, should there be 2 copy ctors:
one with a const reference and one with a const volatile reference?

I have seen a lot written about const correctness and how to design a class
to support both const and non-const instances. I haven't seen anything
written about designing a class to support any flavour of volatile
instances. I agree that volatile should be avoid but there are cases where
it may be necessary.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Mon, 9 Jul 2001 15:32:27 GMT
Raw View
In article <9i5kfj$7rk$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> writes
>Yup. That is what it says (now that I re-read this section a few times :-).
>It really is a mystery to me why it explicitly states nonvolatile const type
>for cv1 here. I don't understand how the addition of the volatile qualifier
>to the reference parameter would make the design less safe (or sound). Its
>not as if adding volatile makes the parameter mutable. Perhaps someone
>remembers why this restriction exists in 8.5.3p5.

Well it does make it mutable (elsewhere, out of sight) but I have
already demonstrated that this is even true of const objects if they
have mutable data.


Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Mon, 9 Jul 2001 19:11:34 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:qeP$7EB8itR7EwI9@ntlworld.com...
> In article <9i5kfj$7rk$1@bcarh8ab.ca.nortel.com>, Gary Mussar
> <mussar@nortelnetworks.com> writes
> >Yup. That is what it says (now that I re-read this section a few times
:-).
> >It really is a mystery to me why it explicitly states nonvolatile const
type
> >for cv1 here. I don't understand how the addition of the volatile
qualifier
> >to the reference parameter would make the design less safe (or sound).
Its
> >not as if adding volatile makes the parameter mutable. Perhaps someone
> >remembers why this restriction exists in 8.5.3p5.
>
> Well it does make it mutable (elsewhere, out of sight) but I have
> already demonstrated that this is even true of const objects if they
> have mutable data.


I understand how the mutable keyword allows const objects to have non-const
members. And I believe I understand that binding rvalue temporaries to const
references is allowed because a const reference should not permit the
temporary rvalue to be changed (this is what I think you are referring to as
the "spirit of the standard"). The mutable feature allows designers to
violate the "spirit of the standard". I would not disagree with this point.

I am still confused with how const volatile references are different from
const references in the "spirit of the standard". I must be missing
something subtle (or maybe not so subtle). Section 8.5.3p5 explicitly
excludes binding to volatile const references. I would still like to find
out if there is some valid (albeit subtle) reason why a const volatile
reference could not be used for such a binding.

Perhaps volatile just gets 2nd class treatment in the language. It wouldn't
be the first time. Even the cast operation to change the volatile specifier
is called const_cast<>. :-)

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Mon, 9 Jul 2001 20:09:39 GMT
Raw View
In article <9icuoe$m9b$1@bcarh8ab.ca.nortel.com>, Gary Mussar
<mussar@nortelnetworks.com> writes
>I am still confused with how const volatile references are different from
>const references in the "spirit of the standard". I must be missing
>something subtle (or maybe not so subtle).

Because const volatile things are not immutable, they just cannot be
changed here. Now as we are talking about temporaries, what does it mean
to have a volatile temporary?


Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://www.research.att.com/~austern/csc/faq.html                ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Fri, 6 Jul 2001 03:59:46 GMT
Raw View
The standard states that a temporary that is an rvalue cannot be bound to a
non-const reference for parameter passing. There are 4 possible cv qualified
types for class T: T, const T, volatile T and const volatile T. Is a const
volatile reference considered a const reference or a non-const reference?
The GNU compiler certainly treats a const volatile reference parameter as a
non-const reference and issues a diagnostic.

I'm trying to determine whether this is a bug in g++, an ambiguity in the
standard or my incomplete understanding of the standard. Any opinion would
be appreciated.

Gary


---
[ 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://www.research.att.com/~austern/csc/faq.html                ]