Topic: Templated cast operator


Author: kanze.james@neuf.fr (James Kanze)
Date: Fri, 2 Jun 2006 20:42:06 GMT
Raw View
Victor Bazarov wrote:
 > uvts_cvs@yahoo.com wrote:
 >>> Isn't it also true that we can just as well cast a 'foo' object to
 >>> 'long' or 'char' or 'double'?

 >> But the integral 1 is int. So why the compiler needs to cast
 >> something to double if the left operand is int? The built-in
 >> operator+ takes to operands of the same type. Is this
 >> correct?

 > The built-in operator + takes either both operands of
 > arithmetic types or pointers on its left and arithmetic on its
 > right.

Or an arithmetic type on the right and a pointer on the left.

 > Nothing I could find in the Standard requires the types to be
 > the same.

=A75.7/1 "The usual arithmetic conversions are performed for
operands of arithmetic or enumeratino type." and =A75/9, which
explains how a common type is determined.  The types which are
added will both be the same, if they are both arithmetic types.

More important here is =A713.6, which defines how the built in
operators are considered when doing overload resolution.  And to
my surprise, there you are right. =A713.6.12: "For every pair of
promoted arithmetic types L and R, there exist candidate
operator functions of the form [...] LR operator+(L, R) [...]
where LR is the result of the usual arithmetic conversions
between types L and R.  Which means that operator+(int, double)
and operator+(int, int) are both candidate functions, both
are equally good, and so the expression is ambiguous.  (I don't
know why, but I was convinced that the only candidate functions
-- except for those involving pointers, of course -- were of the
form T operator+(T, T).)

 > The intergral promotions and arithmetic conversions do apply,
 > however.

Yes, but only after overload resolution has chosen the
appropriate candidate function.

--=20
James Kanze                                    kanze.james@neuf.fr
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France +33 (0)1 30 23 00 34

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: kanze.james@neuf.fr (James Kanze)
Date: Fri, 2 Jun 2006 20:43:04 GMT
Raw View
SuperKoko wrote:
 > kanze wrote:
 >> In the case of overloading, the compiler assimilates the
 >> built-in operators to set of overloaded functions.  In the
 >> case of +, functions which take 2 parameters.  It then
 >> chooses the one function which is 1) a better match than any
 >> other for at least one argument, and 2) no worse match for
 >> any other argument.  In this case, operator+(int,int) is the
 >> best match argument 1, and all possible functions are equal
 >> matches for argument 2 (so operator+(int,int) is not a worse
 >> match).

 >> Thus, I think that this is legal.  The only possible ambiguity
 >> would be between foo::operator T<int>() and foo::operator
 >> T<const int>().  (CV qualification conversions rank as an exact
 >> match.)  But these are two instantiations of the same function
 >> template, and the rules say that template argument deduction
 >> will only find a single instantiation for each function
 >> template.

 > But operator+(int, type*) for any type, is a match as good as
 > operator+(int,int).
 > Should not the compiler say something like:
 > Ambiguous call, best match are:
 > operator+(int,int)
 > operator+(int,char*)
 > operator+(int,int*)
 > operator+(int,any_other_type*)

Good point.  And as Victor Bazarov has pointed out,
operator(int,double), etc. are also candidate functions (which
seems wrong to me).

It is somewhat more complicated than that, however (and I forgot
this point in my earlier postings).  The version of the
conversion operator which is chosen is done by template argument
deduction, not by operator overload resolution.  Still, I now
think that the only thing that this changes is where the
ambiguity is detected -- type resolution fails because the
context provides an exact match for several different types.
(See =A714.8.2.3 for details.)  In fact, I think it would still be
ambiguous in a case like:
     void f(int, int) ;
     void f(double, double) ;
     f( 42, foo() ) ;
because template type deduction must be done before overload
resolution, and the type deduction will fail, because it doesn't
look at the first argument to f, finds two equally good targets
which match, and is thus ambiguous.

At least, I think so now:-).

--=20
James Kanze                                    kanze.james@neuf.fr
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France +33 (0)1 30 23 00 34

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: uvts_cvs@yahoo.com
Date: Thu, 1 Jun 2006 13:24:54 CST
Raw View
Hi everybody, do you think the next little chunk of code has to
compile?

struct foo
{
   template <typename T> operator T() const {return T();}
};

int main()
{
   return 1 + foo();
}

I thought that it has to compile because we can cast the foo object to
int and pass it to operator +, but some compilers seem not to agree
with me (but some others do!). What do you think? Does it adhere to the
ISO standard?

Thanks a lot, Daniele.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "Victor Bazarov" <v.Abazarov@comAcast.net>
Date: Thu, 1 Jun 2006 14:45:59 CST
Raw View
uvts_cvs@yahoo.com wrote:
> Hi everybody, do you think the next little chunk of code has to
> compile?
>
> struct foo
> {
>   template <typename T> operator T() const {return T();}
> };
>
> int main()
> {
>   return 1 + foo();
> }
>
> I thought that it has to compile because we can cast the foo object to
> int and pass it to operator +, but some compilers seem not to agree
> with me (but some others do!). What do you think? Does it adhere to
> the ISO standard?

Isn't it also true that we can just as well cast a 'foo' object to
'long' or 'char' or 'double'?  So, how (on what basis) should the
compiler pick 'int' here?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: uvts_cvs@yahoo.com
Date: Fri, 2 Jun 2006 00:51:47 CST
Raw View
> Isn't it also true that we can just as well cast a 'foo' object to
> 'long' or 'char' or 'double'?

But the integral 1 is int. So why the compiler needs to cast something
to double if the left operand is int? The built-in operator+ takes to
operands of the same type. Is this correct?

Daniele.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Fri, 2 Jun 2006 14:56:49 GMT
Raw View
uvts_cvs@yahoo.com wrote:
>> Isn't it also true that we can just as well cast a 'foo' object to
>> 'long' or 'char' or 'double'?
>
> But the integral 1 is int. So why the compiler needs to cast something
> to double if the left operand is int? The built-in operator+ takes to
> operands of the same type. Is this correct?

The built-in operator + takes either both operands of arithmetic types
or pointers on its left and arithmetic on its right.  Nothing I could
find in the Standard requires the types to be the same.  The intergral
promotions and arithmetic conversions do apply, however.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Fri, 2 Jun 2006 09:56:08 CST
Raw View
Victor Bazarov wrote:
> uvts_cvs@yahoo.com wrote:
> > Hi everybody, do you think the next little chunk of code has
> > to compile?

> > struct foo
> > {
> >   template <typename T> operator T() const {return T();}
> > };

> > int main()
> > {
> >   return 1 + foo();
> > }

> > I thought that it has to compile because we can cast the foo
> > object to int and pass it to operator +, but some compilers
> > seem not to agree with me (but some others do!). What do you
> > think? Does it adhere to the ISO standard?

> Isn't it also true that we can just as well cast a 'foo'
> object to 'long' or 'char' or 'double'?  So, how (on what
> basis) should the compiler pick 'int' here?

In the case of overloading, the compiler assimilates the
built-in operators to set of overloaded functions.  In the case
of +, functions which take 2 parameters.  It then chooses the
one function which is 1) a better match than any other for at
least one argument, and 2) no worse match for any other
argument.  In this case, operator+(int,int) is the best match
argument 1, and all possible functions are equal matches for
argument 2 (so operator+(int,int) is not a worse match).

Thus, I think that this is legal.  The only possible ambiguity
would be between foo::operator T<int>() and foo::operator
T<const int>().  (CV qualification conversions rank as an exact
match.)  But these are two instantiations of the same function
template, and the rules say that template argument deduction
will only find a single instantiation for each function
template.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Fri, 2 Jun 2006 10:57:35 CST
Raw View
kanze wrote:
> In the case of overloading, the compiler assimilates the
> built-in operators to set of overloaded functions.  In the case
> of +, functions which take 2 parameters.  It then chooses the
> one function which is 1) a better match than any other for at
> least one argument, and 2) no worse match for any other
> argument.  In this case, operator+(int,int) is the best match
> argument 1, and all possible functions are equal matches for
> argument 2 (so operator+(int,int) is not a worse match).
>
> Thus, I think that this is legal.  The only possible ambiguity
> would be between foo::operator T<int>() and foo::operator
> T<const int>().  (CV qualification conversions rank as an exact
> match.)  But these are two instantiations of the same function
> template, and the rules say that template argument deduction
> will only find a single instantiation for each function
> template.
>
But operator+(int, type*) for any type, is a match as good as
operator+(int,int).
Should not the compiler say something like:
Ambiguous call, best match are:
operator+(int,int)
operator+(int,char*)
operator+(int,int*)
operator+(int,any_other_type*)

---
[ 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.comeaucomputing.com/csc/faq.html                      ]