Topic: Implicit casts.
Author: djones@megatest.com (Dave Jones)
Date: Wed, 17 Feb 1993 04:38:14 GMT Raw View
[My appologies if you receive more than one copy of this. I'm having
a fight with my mailer over the Newgroups line. It keeps complaining about
"whitespace".]
I have a proposal or two.
What prompted this the YARSC I recently wrote -- yet another reference-
counted string class.
I want to be able to do stuff like this:
Char_String str = "foo";
str.append("bar");
str.append(str);
cout << str; // writes foobarfoobar
Many of the functions should be able to take either a (reference-counted)
Char_String or a plain C++ literal string as append() does above. Since
several of the functions take two string arguments, providing overloaded
functions for all the combinations is too long winded. Looks like a job for
implicit type-conversions of the function arguments.
We don't want implicit conversion of const char* to Char_String, because
the Char_String constructor that takes a char* is the one that does
the str = "foo" above. It necessarily copies the string because the class
can not tell when using the assigned string itself is safe. But we want to
avoid the copy when passing parameters to member-functions with read-only
parameters.
So what we want is an implicit cast of Char_String to const char*.
Gotcha number one is found on page 232 of Stroustrup's bible, 2nd edition:
"There can be no implicit conversion from a user-defined type to a basic
type (because the basic types are not classes);" So defining an implicit
conversion from Char_String to const char* is right out. Why? Seems like
all that would be needed is a syntax for it. But Okay, I can live with that,
if I must.
So I defined a global class called Char_String_Value. The man-page will say
that either a Char_String or a string literal is permissable anywhere
a Char_String_Value is called for in the function-prototypes. I will not
advertise it as an actual class, but rather as a meta-variable taking the
values Char_Value and const char*.
But gotcha number 2 is that there is no way, other than saying "Don't DO that"
actually to prevent the use of class Char_String_Value in user-written
code. I only want it used in implicit type-conversions from literals and
Char_String's in function calls. I don't want to try to hide its existence,
because it is going to show up when the users are running debuggers on
their code. Saying not to use it directly is certainly good enough, but somehow
it seems inelegant.
How about a keyword specifying that a constructor is a type-conversion
operator only? In addition to "public" and "private", how about "implicit",
meaning, to be used only in implicit type-conversions on compiler-generated
temporary objects (by-value arguments and return values)? ... not to be
used to declare static, automatic, or dynamic (operator-new) objects.
class Char_String_Value {
implicit:
Char_String_Value(const char*);
Char_String_Value(const Char_String&);
private:
const char *str;
int length;
public:
int operator == ( const Char_String_Value&) const;
int operator < ( const Char_String_Value &) const;
// et cetera
};
.. or am I missing the "right" way to do this?