Topic: implicit conversions


Author: inpact3 <inpact3@clr34el.der.edf.fr>
Date: 1997/08/08
Raw View
I have a big problem : the following code (that demonstrates a trick
which should reduce implicit conversions danger) compiles fine with
Sun C++ 4.0.1 (and 4.1) compiler, but gives errors with xlC on AIX 4.1.

//----------------------------------------------------------------
  class string
  {
    private:
      class Dummy {};
      operator Dummy * () const;   //-- undefined
      //-- This dummy conversion function shall force compile
      //-- time errors when the class string is used in such
      //-- silly constructs as :
      //
      //--   string str("foo');
      //--   if (str) delete str;

    public:
      operator const char * () const { ... }
      ...
  };

  main()
  {
  string str ("foo");
  cout << str;          //-- Here : ambiguity for xlC
  }
//----------------------------------------------------------------

I tried to find which compiler (sun or AIX) was wrong by reading
carefully the CD2. My conclusion is rather strange : if i did not
misunderstand something, both are right !!!


For the "cout << str" call,  there is two viable functions :

  ostream::operator<< (const char *)       func1
  ostream::operator<< (const void *)       func2

For the first one, the implicit conversion sequence is :

  string --> const char *  (user-defined)

For func2, two implicit conversion sequences exist :

  string --> const char * -> const void *    (user-defined)
  string --> Dummy * -> const void *         (user-defined)

Neither is better than the other (two user-defined sequences can
be compared only if they use the same conversion function. See
[over.ics.rank] alinea 3).

In this case, the compiler shall pick one of them randomly and,
if the viable function that use it (func2) is found as the best,
the call will be ill-formed (see [over.best.ics] alinea 10).

Scenario 1 : the compiler picks the first conversion sequence
--------------------------------------------------------------

To find the best viable function, the compiler tries to compare the
implicit conversion sequences for all arguments (see [over.match.best]).

In this case, ICS1(func1) is not worse than ICS1(func2) and
ICS2(func1) is better than ICS2(func2) :

ICS2(func1) = string --> const char *
ICS2(func2) = string --> const char * -> const void *

According to [over.ics.rank] alinea 3, one user-defined sequence is
better than another if :
- they both use the same conversion function   (that's the case)
- the second standard conversion sequence of the former has a better
rank than the latter (here, we have "exact match" vs. "conversion").

So, func1 is the better than func2. The call is not ill-formed because
func2 has not been selected (see [over.best.ics] alinea 10).

Scenario 2 : the compiler picks the second conversion sequence
---------------------------------------------------------------

In this case, ICS2(func1) is neither better nor worse than ICS2(func2)
because they don't use the same conversion function.

Therefore, func1 is neither better nor worse than func2.
The call is ill-formed.



So, where is my error ? I can't imagine that the draft let a compiler
choose between alternatives, knowing that only one will make a program
ill-formed.


 Thanks for reading,
 Jerome CHAROUSSET
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]