From: tmb@arolla.idiap.ch (Thomas M. Breuel)
Newsgroups: comp.lang.c++
Subject: Re: defining cast operators outside classes
Date: 9 Sep 92 01:51:04 GMT
Reply-To: tmb@idiap.ch
Organization: IDIAP (Institut Dalle Molle d'Intelligence Artificielle
	Perceptive)
In-reply-to: steve@taumet.com's message of 8 Sep 92 17:36:13 GMT

In article <1992Sep8.173613.25113@taumet.com> steve@taumet.com (Steve Clamage) writes:

   tmb@arolla.idiap.ch (Thomas M. Breuel) writes:

   >Apparently, it is impossible to define a conversion operator for a
   >class without making the conversion operator a member function.

   In the case of some operators you run the risk of having legal code
   with different meanings depending on whether the operator declaration
   is visible.

Why is the C++ committee suddenly so concerned with my well-being?
Those people who feel that such a feature is dangerous simply don't
define conversion operators outside their classes.

   The semantics depend on which non-class declarations are visible,
   which is not normally the case in C++.  (There is a somewhat
   parallel case:  You omit one overloaded function declaration and
   an unintended function is called.  Maybe someone can think of a way
   to solve that problem in the language.)

As you yourself point out, the problem is analogous to "subtle bugs"
that come from overloading. I'm in general no friend of either
overloading or automatic conversions precisely because they make a new
class of subtle bugs possible. But given that C++ has gone down this
path so far (and sacrificed a lot in other kinds of potential
notational conveniences for it), I'd just as much have all the
facilities and not be limited in arbitrary ways.

   In the case of conversions, it is likely that the conversion function
   would need to be a friend function, thus needing to appear in the
   class definition anyway.

I don't find that to be true at all. And, in fact, there are good
reasons why conversion operators tend _not_ to need to look at the
internals of data structures in many cases.  Conversions tend to be
used in cases where visible properties of an object are preserved but
representation is changed. Hence, conversions mainly "take data out"
of one public interface and "stuff it into" another public interface.
Concretely, in the case of matrices:

     operator SomeMatrix(OtherMatrix &m) {
        SomeMatrix result(m.dim(0),m.dim(1));
        for(int i=0;i<m.dim(0);i++)
           for(int j=0;j<m.dim(1);j++)
              result(i,j) = m(i,j);
        return result;
     }

   If you need to create an ad-hoc conversion from class A to class B
   when you don't own class A, you can make a B constructor taking an A.
   If you don't own class B either, you can write an ordinary function
   which does the conversion.

Yes, thank you, I knew that. By that argument, we might do away with
virtual functions and classes as well, since the can be replaced by
function pointers and structures.

   In the end, the restriction elminates a source of dangerous but subtle
   bugs while creating virtually no extra inconvenience.

I disagree on both points. If you don't use the feature, you don't get
the class of bugs that can result from it (just like if you don't use
multiple inheritance, you don't get MI bugs). And, it does create
"extra inconvenicence" because...

   The only
   inconvenience I can see occurs when ALL of these are met simultaneously:
	   - You need to convert an A to a B.
	   - You can't modify A or B.
	   - Everything needed to do the conversion is public.
	   - You want implicit conversion, not "b = A_to_B(a)".

Yes, and these conditions are frequently met in mathematical/numerical
software, where you have to convert between different vector
datatypes, etc. Implicit conversions are useful because you don't want
to clutter your already complicated equations with conversions; in
fact, mathematical/numerical objects are the _only_ place where I like
to use overloading or implicit conversions.

In summary, allowing the user to define conversion operators outside
classes would remove an arbitrary restriction from C++. I don't think
it is any more dangerous than, say, overloading, and you are immune
from "its subtle bugs" if you don't use the feature.

					Thomas.
Newsgroups: comp.lang.c++