Topic: Defect Report: inconsistency in user defined conversion sequences returning references
Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/06/09 Raw View
[ forwarded to C++ committee. -sdc ]
There is an inconsistency in the handling of references vs. pointers in user
defined conversions and overloading. The reason for that is, that the combination
of 8.5.3 and 4.4 circumvents the standard way of ranking conversion function,
which was probably not the intention of the designers of the standard.
Let's start with some examples, to show what it is about:
---------------------------------------------------
struct Z { Z(){} };
struct A {
Z x;
operator Z *() { return &x; }
operator const Z *() { return &x; }
};
struct B {
Z x;
operator Z &() { return x; }
operator const Z &() { return x; }
};
main()
{
A a;
Z *a1=a;
const Z *a2=a; // not ambiguous
B b;
Z &b1=b;
const Z &b2=b; // ambiguous
}
---------------------------------------------------
So while both classes A and B are structurally equivalent, there is a difference
in operator overloading. I want to start with the discussion of the pointer case
(const Z *a2=a;): 13.3.3 is used to select the best viable function. Rule 4 selects
A::operator const Z*() as best viable function using 13.3.3.2 since the implicit
conversion sequence 'const Z*' -> 'const Z*' is a better conversion sequence than
'Z*' -> 'const Z*'.
So what is the difference to the reference case? cv-qualification conversion
is only applicable for pointers according to 4.4. According to 8.5.3/4-7 references
are initialized by binding using the concept of reference-compatibility. The problem
with this is, that in this context of binding, there is no conversion, and therefore
there is also no comparing of conversion sequences. More exactly all conversions can be
considered identity conversions according to 13.3.3.1.4/1, which compare equal and
which has the same effect.
So binding 'const Z*' to 'const Z*' is as good as binding 'const Z*' to 'Z*' in terms
of overloading. Therefore 'const Z &b2=b;' is ambiguous.
[13.3.3.1.4/5 and 13.3.3.2/3 rule 3 (S1 and S2 are reference bindings ...) do not
seem to apply to this case]
There are other ambiguities, that result in the special treatment of references:
Example:
---------------------------------------------------
struct A {int a;};
struct B: public A { B() {}; int b;};
struct X {
B x;
operator A &() { return x; }
operator B &() { return x; }
};
main()
{
X x;
A &g=x; // ambiguous
}
---------------------------------------------------
Since both references of class A and B are reference compatible with
references of class A and since from the point of ranking of implicit conversion
sequences they are both identity conversions, the initialization is ambiguous.
So why should this be a defekt?
- References behave fundamentally different from pointers in combination
with user defined conversions, although there is no reason to have this
different treatment.
- this difference only shows up in combination with user defined conversion
sequences, for all other cases, there are special rules, e.g. 13.3.3.2/3 rule 3.
So overall I think this was not the intention of the authors of the standard.
So how could this be fixed? For comparing conversion sequences (and only for
comparing) reference binding should be treated as if it was a normal
assignment/initialization and cv_qualification would have to be defined for
references. This would affect 8.5.3/6, 4.4 and probably 13.3.3.2/3.
Another fix could be to add a special case in 13.3.3/1.
Thanks go to all and especially to Hideaki Onaru who helped to find out, what
was wrong with the overloading of user defined conversions returning references.
(The thread was "which compiler is right" on comp.std.c++)
- Matthias Meixner
--
Matthias Meixner meixner@rbg.informatik.tu-darmstadt.de
Technische Universit t Darmstadt
Rechnerbetriebsgruppe Telefon (+49) 6151 16 6670
Wilhelminenstra e 7, D-64283 Darmstadt, Germany Fax (+49) 6151 16 4701
[ 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 ]