Topic: uder-defined conversion and built-in operator=


Author: Alexander Schiemann <aschiem@math.uni-sb.de>
Date: 2000/10/20
Raw View

Stephen Clamage wrote:

> On Mon,  2 Oct 2000 14:57:57 GMT, scott douglass <sdouglass@arm.com>
> wrote:
>
> >Steve Clamage (someone I should know better than to disagree with in a
> >public forum) wrote:
> >>On Fri, 29 Sep 2000 12:46:12 CST, scott douglass <sdouglass@arm.com>
> >>wrote:
> >>
> >> >struct T {
> >> >   operator short() const;
> >> >   operator int() const;
> >> >};
> >> >
> >> >short s;
> >> >
> >> >void f(const T& t) {
> >> >   s = t;
> >> >}
> >>
> >>Section 5.17 says that in an assignment, the right side is implicitly
> >>converted to the type of the left side. The left side has type short.
> >
> >Yes, I had read 5.17.  But, I think the overload resolution for operator=
> >happens first including choosing the user-defined conversions -- if the
> >overload resolution selects a built-in operator= then 5.17 applies to the
> >result of the selected conversion (e.g. 'long l; l = t;' still needs an
> >implicit conversion after the user-defined conversion).
> >
> >>There are two conversions available from type T: to short and to int.
> >>Function T::operator short() is an exact match, and the int conversion
> >>is a match after a standard conversion (from int to short). Therefore
> >>the T conversion to short is preferred.
> >
> >You seem to be choosing the user-defined conversion after the overload
> >resolution has chosen the built-in operator= ...
>
> That's because there is only one viable candidate assignment operator.
>
> There is no user-defined operator= in the example, and there is no
> built-in operator= that will assign a class type to a simple type.
>
> Section 13.6 defines the built-in operators for purposes of overload
> resolution. For non-pointer types, the operators have the form
>         VQ T& operator=(VQ T&, T);
>

I do not find this operator in the Standart, instead sec. 13.6 clause 18
(p. 133) reads:
For every triple (L, VQ, R), where L is an arithmetic type, VQ is either
volatile or empty,
and R is a promoted arithmetic type, there exist candidate operator functions
of the form
  VQ L& operator=( VQ L&, R );

Which clause of sec 13.6 states VQ T& operator=(VQ T&, T); ?


> where VQ is either "volatile" or empty. There is a built-in
>         short& operator=(short&, short) // viable
> but there is no
>         short& operator=(short&, int) // no such operator
>
> The set of viable assignment operators thus has only one member:
>         short& operator=(short&, short)
>
> ---

Alexander Schiemann



---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: scott douglass <sdouglass@arm.com>
Date: 2000/10/11
Raw View
Steve Clamage wrote:
>On Mon,  2 Oct 2000 14:57:57 GMT, scott douglass <sdouglass@arm.com>
>wrote:
>
> >Steve Clamage (someone I should know better than to disagree with in a
> >public forum) wrote:
> >>On Fri, 29 Sep 2000 12:46:12 CST, scott douglass <sdouglass@arm.com>
> >>wrote:
> >>
> >> >struct T {
> >> >   operator short() const;
> >> >   operator int() const;
> >> >};
> >> >
> >> >short s;
> >> >
> >> >void f(const T& t) {
> >> >   s = t;
> >> >}
>[...]
>
>That's because there is only one viable candidate assignment operator.
>
>There is no user-defined operator= in the example, and there is no
>built-in operator= that will assign a class type to a simple type.

We agree so far.

>Section 13.6 defines the built-in operators for purposes of overload
>resolution. For non-pointer types, the operators have the form
>         VQ T& operator=(VQ T&, T);

I disagree.  If this is from 13.6/20 then T must be an enumeration or
pointer to member type -- which is not the case here.  If this is not from
13.6/20 then I missed it -- please point it out to me.

>where VQ is either "volatile" or empty. There is a built-in
>         short& operator=(short&, short) // viable
>but there is no
>         short& operator=(short&, int) // no such operator
>
>The set of viable assignment operators thus has only one member:
>         short& operator=(short&, short)

I still disagree.  From 13.6/18:
 >>
For every triple (L, VQ, R), where L is an arithmetic type, VQ is either
volatile or empty, and R is a promoted arithmetic type, there exist
candidate operator functions of the form

         VQ L& operator=(VQ L&, R);
         [...]
<<

This does not include
         short& operator=(short&, short)
because R can't be 'short' since 'short' is not a "promoted arithmetic
type".  But it does include these (if I correct understand the term
"promoted arithmetic type"):
         short& operator=(short&, int)
         short& operator=(short&, unsigned int)
         short& operator=(short&, long)
         short& operator=(short&, unsigned long)
         short& operator=(short&, float)
         short& operator=(short&, double)
         short& operator=(short&, long double)

I think these are all viable and the first one is the best match and
'T::operator short() const' does not get used.

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Stephen Clamage <stephen.clamage@sun.com>
Date: 2000/10/09
Raw View
On Mon,  2 Oct 2000 14:57:57 GMT, scott douglass <sdouglass@arm.com>
wrote:

>Steve Clamage (someone I should know better than to disagree with in a
>public forum) wrote:
>>On Fri, 29 Sep 2000 12:46:12 CST, scott douglass <sdouglass@arm.com>
>>wrote:
>>
>> >struct T {
>> >   operator short() const;
>> >   operator int() const;
>> >};
>> >
>> >short s;
>> >
>> >void f(const T& t) {
>> >   s = t;
>> >}
>>
>>Section 5.17 says that in an assignment, the right side is implicitly
>>converted to the type of the left side. The left side has type short.
>
>Yes, I had read 5.17.  But, I think the overload resolution for operator=
>happens first including choosing the user-defined conversions -- if the
>overload resolution selects a built-in operator= then 5.17 applies to the
>result of the selected conversion (e.g. 'long l; l = t;' still needs an
>implicit conversion after the user-defined conversion).
>
>>There are two conversions available from type T: to short and to int.
>>Function T::operator short() is an exact match, and the int conversion
>>is a match after a standard conversion (from int to short). Therefore
>>the T conversion to short is preferred.
>
>You seem to be choosing the user-defined conversion after the overload
>resolution has chosen the built-in operator= ...

That's because there is only one viable candidate assignment operator.

There is no user-defined operator= in the example, and there is no
built-in operator= that will assign a class type to a simple type.

Section 13.6 defines the built-in operators for purposes of overload
resolution. For non-pointer types, the operators have the form
 VQ T& operator=(VQ T&, T);
where VQ is either "volatile" or empty. There is a built-in
 short& operator=(short&, short) // viable
but there is no
 short& operator=(short&, int) // no such operator

The set of viable assignment operators thus has only one member:
 short& operator=(short&, short)

---
Steve Clamage, stephen.clamage@sun.com

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: scott douglass <sdouglass@arm.com>
Date: 2000/09/29
Raw View
Hello,

I think the standard specifies that the following function calls
'T::operator int() const' but most of the compilers I have access to
disagree with me.  Furthermore I think most users do not want the behavior
the standard requires.

struct T {
   operator short() const;
   operator int() const;
};

short s;

void f(const T& t) {
   s = t;
}

I think the best built-in operator (13.6) is 'short& operator=(short&,
int);' and so the user-defined conversion 'T::operator int() const' should
be selected.

I don't think 'short& operator=(short&, short)' exists and I don't think
13.3.1.4 applies because this is not a copy-initialization.

Am I right or is everyone else?

If I'm right:  Is this the behavior that users want/expect?


There is this from 5.17:
 >>
If the left operand is not of class type, the expression is implicitly
converted (clause 4) to the cv-unqualified type of the left operand.
<<

But I think this applies only after the user-defined conversion has been
applied according to the choice made in 13.3.1.2/13.6.

I think most users want/expect 'T::operator short() const' to be
selected.  I'm not sure what the best change to standard would be to get
this behavior.  Perhaps changing the built-in operator= to accept any
arithmetic or enum type for the second argument would achieve the desired
effect.

I also am not sure what I feel about the other assignment operators:
 s *= t;

Again, choosing 'T::operator short() const' might be expected but it would
break the usual relationship with 's = s * t' which has to choose
'T::operator int() const'.

One compiler I have access to says this is ambiguous -- but I don't think
that's right.

---
[ 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: Roger Orr <roger_orr@my-deja.com>
Date: 2000/10/01
Raw View
In article <4.3.2.7.2.20000929121421.02c6bd38@mail1>,
  scott douglass <sdouglass@arm.com> wrote:
> Hello,
>
> I think the standard specifies that the following function calls
> 'T::operator int() const' but most of the compilers I have access to
> disagree with me.  Furthermore I think most users do not want the
behavior
> the standard requires.
>
> struct T {
>    operator short() const;
>    operator int() const;
> };
>
> short s;
>
> void f(const T& t) {
>    s = t;
> }
>
> I think the best built-in operator (13.6) is 'short& operator=
(short&,
> int);' and so the user-defined conversion 'T::operator int() const'
should
> be selected.
>
> I don't think 'short& operator=(short&, short)' exists and I don't
think
> 13.3.1.4 applies because this is not a copy-initialization.
>
> Am I right or is everyone else?
>
Hmmm .. I suspect you might be right.  Looks like another case where
user-defined conversions can be dangerous.

>
> One compiler I have access to says this is ambiguous -- but I don't
think that's right.

Perhaps not, but I think it is _conceptually_ ambiguous to provide a
UDC to both short and int !

Roger.
--
MVP in C++ for Brainbench at http://www.brainbench.com


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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: Stephen Clamage <stephen.clamage@sun.com>
Date: 2000/10/01
Raw View
On Fri, 29 Sep 2000 12:46:12 CST, scott douglass <sdouglass@arm.com>
wrote:

>I think the standard specifies that the following function calls
>'T::operator int() const' but most of the compilers I have access to
>disagree with me.

As do I. :-)

>struct T {
>   operator short() const;
>   operator int() const;
>};
>
>short s;
>
>void f(const T& t) {
>   s = t;
>}

Section 5.17 says that in an assignment, the right side is implicitly
converted to the type of the left side. The left side has type short.

There are two conversions available from type T: to short and to int.
Function T::operator short() is an exact match, and the int conversion
is a match after a standard conversion (from int to short). Therefore
the T conversion to short is preferred.

I can't follow the reasoning you supplied that resulted in selecting
the int conversion. You seem to assume things that I don't find in the
standard.

---
Steve Clamage, stephen.clamage@sun.com

---
[ 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: scott douglass <sdouglass@arm.com>
Date: 2000/10/02
Raw View
Steve Clamage (someone I should know better than to disagree with in a
public forum) wrote:
>On Fri, 29 Sep 2000 12:46:12 CST, scott douglass <sdouglass@arm.com>
>wrote:
>
> >I think the standard specifies that the following function calls
> >'T::operator int() const' but most of the compilers I have access to
> >disagree with me.
>
>As do I. :-)
>
> >struct T {
> >   operator short() const;
> >   operator int() const;
> >};
> >
> >short s;
> >
> >void f(const T& t) {
> >   s = t;
> >}
>
>Section 5.17 says that in an assignment, the right side is implicitly
>converted to the type of the left side. The left side has type short.

Yes, I had read 5.17.  But, I think the overload resolution for operator=
happens first including choosing the user-defined conversions -- if the
overload resolution selects a built-in operator= then 5.17 applies to the
result of the selected conversion (e.g. 'long l; l = t;' still needs an
implicit conversion after the user-defined conversion).

>There are two conversions available from type T: to short and to int.
>Function T::operator short() is an exact match, and the int conversion
>is a match after a standard conversion (from int to short). Therefore
>the T conversion to short is preferred.

You seem to be choosing the user-defined conversion after the overload
resolution has chosen the built-in operator= -- and choosing a different
user-defined conversion than overload resolution used.  What built-in
operator= do you think is being chosen by overload resolution.

>I can't follow the reasoning you supplied that resulted in selecting
>the int conversion. You seem to assume things that I don't find in the
>standard.

5/3 says:
 >>
Clause 5 defines the effects of operators when applied to types for which
they have not been overloaded.  Operator overloading shall not modify the
rules for the built-in operators, that is, for operators applied to types
for which they are defined by this Standard. However, these built-in
operators participate in overload resolution, and as part of that process
user-defined conversions will be considered where necessary to convert the
operands to types appropriate for the built-in operator. If a built-in
operator is selected, such conversions will be applied to the operands
before the operation is considered further according to the rules in clause
5; see 13.3.1.2, 13.6.
<<

To me the last sentence of this clearly means that the user-defined
conversions are selected by overload resolution before 5.17 has effect.  I
believe that overload resolution for operator= has to choose the built-in
         short& operator=(short&, int);
And that uses 'T::operator int() const'.

---
[ 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              ]