Topic: Implicit conversion before ->*
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Tue, 22 Jun 1993 03:32:15 GMT Raw View
In article <DOUGM.93Jun11234759@titan.cs.rice.edu> dougm@titan.cs.rice.edu (Doug Moore) writes:
>I recently posed a question to this group that I posed badly. In an
>email exchange, I got some information, but not the answer I seek. So
>I'm trying again, more carefully.
>
>In the expression a->*b, where a is an object of class type that
>provides a user-defined conversion to T*, and b is a pointer to a
>member of T, and operator ->* has not been overloaded, is a->*b
The issue of when (if ever) user-defined conversions may be (or are) applied
to operands of built-in operators (in order to render the operand(s) acceptable
for the operator in question) has been raised (by me) as an open issue with
x3j16.
Experience with existing compilers indicates that some such user-defined
conversions will be applied in some contexts by some compilers. For
example, given:
struct S { operator int* () { printf ("Made it!\n"); } object;
void callee ()
{
*object;
}
...many compilers will indeed invoke the user-defined type conversion
operator. The rules for all such cases are less than abundantly clear
however. For example, the good old C operator [] requires one operand
to be a pointer and the other to have some integral type... but the
pointer may be the thing within the []. Thus, in C and C++, the expression
`i[p]' is a valud expression if i has some integral type and p has some
pointer type. As we all know, p[i] is also valid. Given these facts, the
proper interpretation of the following example is left as an exercize for
the reader:
struct S {
operator int ();
operator char * ();
} object;
... object[object] ...
--
-- Ronald F. Guilmette ------------------------------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------
Author: simonh@swidev.demon.co.uk (Simon Huntington)
Date: Tue, 22 Jun 1993 17:53:42 +0000 Raw View
In article <rfgC9075s.728@netcom.com> rfg@netcom.com writes:
>As we all know, p[i] is also valid. Given these facts, the
>proper interpretation of the following example is left as an exercize for
>the reader:
>
> struct S {
> operator int ();
> operator char * ();
> } object;
>
> ... object[object] ...
>
I posted a question about this sort of stuff. The ARM does not define where
conversions can be applied (as you say), but the compilers I have here will
not attempt any conversions on the operands of the subscript operator.
--
Simon Huntington
Software Interrupt Developments. Leeds, UK.
Author: dougm@titan.cs.rice.edu (Doug Moore)
Date: Sat, 12 Jun 1993 05:47:59 GMT Raw View
I recently posed a question to this group that I posed badly. In an
email exchange, I got some information, but not the answer I seek. So
I'm trying again, more carefully.
In the expression a->*b, where a is an object of class type that
provides a user-defined conversion to T*, and b is a pointer to a
member of T, and operator ->* has not been overloaded, is a->*b
1. legal, because a is converted to a T*
2. illegal, because a is not a T*.
Passages in the ARM that refer to operator -> do not apply in this
case; ->* is a binary operator and does not behave like operator ->.
Why this matters
If the answer above is 2, then there is yet another obstacle to the
creation of "smart pointer" types (beyond the conversion problems in
Edelson's article in Usenix C++ '92). One cannot overload a unary ->*
to act just like a unary ->, because ->* isn't unary. To make a->*b
legal for a smart pointer (to class T) a and a member (of T) pointer
b, one must overload binary ->* for all possible member pointer types.
Thus, smart pointer class templates cannot be built that handle member
pointers properly.
Why answer 1 might be right
I offer an analogy.
struct Foo { int d; operator int() {return d;}};
Foo f;
int i,j;
i = f + j; // is this legal?
Sure it is. The conversion to int can be applied to f, even when it
is the argument to an ordinary built-in operator.
So why not:
struct Smart { T* p; operator T*() {return p;}};
Smart s;
int T::*z = &T::idata;
int i;
i = s->*z; // is this legal?
It is if the conversion operator can be applied. As the ARM says
(13.4.6) "... there is nothing special about the binary operator ->*."
(Thanks to John Max Skaller for reminding me of this passage.)
I certainly hope that this conversion can be implicitly applied. I'd
like to start complaining to compiler vendors who don't get it right.
But if the conversion is not implicitly applicable, I'd really
appreciate an explanation of why not, with references to the ARM.
I've been told that the conversion is inapplicable, but I'm not
satisfied with the explanations provided.
Thanks for considering this problem.
Doug Moore
(dougm@cs.rice.edu)