www.digitalmars.com         C & C++   DMDScript  

D - opCast

reply Vathix <vathix dprogramming.com> writes:
Overloading an object to cast to another type:

class Another
{
	char[] str;
	this(char[] init) { str = init; }
	void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)
Jan 20 2004
next sibling parent reply Georg Wrede <Georg_member pathlink.com> writes:
In article <buksgm$1vc1$1 digitaldaemon.com>, Vathix says...
Overloading an object to cast to another type:

class Another
{
	char[] str;
	this(char[] init) { str = init; }
	void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)

This seems so natural that it shouldn't even be a question! :-)
Jan 20 2004
parent reply "davepermen" <davepermen hotmail.com> writes:
wich is the same as operator Type() in c++, wich should be used in as less
cases as possible. the implicit cast that happens can create such a ton of
problems. nope. implicit casting should not be allowed

"Georg Wrede" <Georg_member pathlink.com> schrieb im Newsbeitrag
news:bulas9$2m2u$1 digitaldaemon.com...
 In article <buksgm$1vc1$1 digitaldaemon.com>, Vathix says...
Overloading an object to cast to another type:

class Another
{
 char[] str;
 this(char[] init) { str = init; }
 void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)

This seems so natural that it shouldn't even be a question! :-)

Jan 20 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Wow! I hadn't looked at the example enough to realise that it was proposing
implicit casting.

No way, no how!

"davepermen" <davepermen hotmail.com> wrote in message
news:bulb6u$2mkc$1 digitaldaemon.com...
 wich is the same as operator Type() in c++, wich should be used in as less
 cases as possible. the implicit cast that happens can create such a ton of
 problems. nope. implicit casting should not be allowed

 "Georg Wrede" <Georg_member pathlink.com> schrieb im Newsbeitrag
 news:bulas9$2m2u$1 digitaldaemon.com...
 In article <buksgm$1vc1$1 digitaldaemon.com>, Vathix says...
Overloading an object to cast to another type:

class Another
{
 char[] str;
 this(char[] init) { str = init; }
 void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)

This seems so natural that it shouldn't even be a question! :-)


Jan 21 2004
parent "davepermen" <davepermen hotmail.com> writes:
i think if cast(Type) will switch over to a template syntax, a.k.a.
cast!(Type) we will soon write our own casts in that style.. just like
static_cast!(Type) or similar.. any_cast!(Type), lexical_cast!(Type) etc..

this can be done even now yet.. so it's easy.. but we need type deduction
actually..

uint x = 10;
char[] str = "x = ";
str ~= lexical_cast!(char[],uint)(x);

hm.. if type deduction can not be implemented as is, i propose a new thing:

typeof with the ? operator.. ?x is typeof(x)

so we could at least write:

uint x = 10;
char[] str = "x = ";
str ~= lexical_cast!(char[],?x)(x);

of course,

str ~= lexical_cast!(char[])(x); would be best..

"Matthew" <matthew.hat stlsoft.dot.org> schrieb im Newsbeitrag
news:bulf2o$2u6r$1 digitaldaemon.com...
 Wow! I hadn't looked at the example enough to realise that it was

 implicit casting.

 No way, no how!

 "davepermen" <davepermen hotmail.com> wrote in message
 news:bulb6u$2mkc$1 digitaldaemon.com...
 wich is the same as operator Type() in c++, wich should be used in as


 cases as possible. the implicit cast that happens can create such a ton


 problems. nope. implicit casting should not be allowed

 "Georg Wrede" <Georg_member pathlink.com> schrieb im Newsbeitrag
 news:bulas9$2m2u$1 digitaldaemon.com...
 In article <buksgm$1vc1$1 digitaldaemon.com>, Vathix says...
Overloading an object to cast to another type:

class Another
{
 char[] str;
 this(char[] init) { str = init; }
 void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)

This seems so natural that it shouldn't even be a question! :-)



Jan 21 2004
prev sibling next sibling parent Georg Wrede <Georg_member pathlink.com> writes:
Ok, I don't know enough about this to argue.
But there really should be an easy way to 
use c and d strings in a mixed environment.
Easy meaning less typing.


In article <bulb6u$2mkc$1 digitaldaemon.com>, davepermen says...
wich is the same as operator Type() in c++, wich should be used in as less
cases as possible. the implicit cast that happens can create such a ton of
problems. nope. implicit casting should not be allowed

"Georg Wrede" <Georg_member pathlink.com> schrieb im Newsbeitrag
news:bulas9$2m2u$1 digitaldaemon.com...
 In article <buksgm$1vc1$1 digitaldaemon.com>, Vathix says...
Overloading an object to cast to another type:

class Another
{
 char[] str;
 this(char[] init) { str = init; }
 void opCast(out char* result) { result = toStringz(str); }
}

char[] foo = "hello world";
Another a = new Another(foo[0 .. 5]);
printf(a); //properly null-terminates

How about it?  :)

This seems so natural that it shouldn't even be a question! :-)


Jan 21 2004
prev sibling parent reply Burton Radons <loth users.sourceforge.net> writes:
davepermen wrote:
 wich is the same as operator Type() in c++, wich should be used in as less
 cases as possible. the implicit cast that happens can create such a ton of
 problems. nope. implicit casting should not be allowed

Implicit casting is all right /so long as/ you distinguish between information-increasing casts and information-denuding casts; upcasts and downcasts. Casting from float to int is a downcast; we lose information. The opposite direction is an upcast; the new type has as much information or more (for the purposes of casting). With this information we can solve an equation's casting, handle explicit implicit casting, and generate cogent error messages in case of conflict, such as if there's a mutual upcast. C++ is a particular mess when it comes to this operator. There's no reversability, there's two ways to do one thing, it makes it impossible for implementations to produce a legible error report, and it treats a two-way street as if there's only one way you should want to go. Bloody awful. Don't judge a concept based on a broken implementation.
Jan 21 2004
parent "davepermen" <davepermen hotmail.com> writes:
i'm not sure. i don't really like it by default.

i don't even use implicit casts if i code with integers and floats, just to
make sure i code it really the way i want..

"Burton Radons" <loth users.sourceforge.net> schrieb im Newsbeitrag
news:bunpiu$gtv$1 digitaldaemon.com...
 davepermen wrote:
 wich is the same as operator Type() in c++, wich should be used in as


 cases as possible. the implicit cast that happens can create such a ton


 problems. nope. implicit casting should not be allowed

Implicit casting is all right /so long as/ you distinguish between information-increasing casts and information-denuding casts; upcasts and downcasts. Casting from float to int is a downcast; we lose information. The opposite direction is an upcast; the new type has as much information or more (for the purposes of casting). With this information we can solve an equation's casting, handle explicit implicit casting, and generate cogent error messages in case of conflict, such as if there's a mutual upcast. C++ is a particular mess when it comes to this operator. There's no reversability, there's two ways to do one thing, it makes it impossible for implementations to produce a legible error report, and it treats a two-way street as if there's only one way you should want to go. Bloody awful. Don't judge a concept based on a broken implementation.

Jan 22 2004
prev sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Vathix wrote:
 Overloading an object to cast to another type:

I agree that we need something like that for symmetry. But to be used sparingly. In C++ we had explicit constructors. Maybe also opExplicitCast?
 class Another
 {
     char[] str;
     this(char[] init) { str = init; }
     void opCast(out char* result) { result = toStringz(str); }

or even, let the return type be the type to cast to. char * opCast() { return toStringz(str); } Then i also have another idea. Some functions must be allowed to always implicitly cast their input, even if only explicit cast is defined for the input. Example: void sillyPrint(cast(char*) string) { /+...+/ } Now, given any type, for which explicit or implicit cast is defined, it would be implicitly cast to char* when fed to this function. -eye
Jan 23 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Ilya Minkov" <minkov cs.tum.edu> wrote in message
news:bus46u$1ljc$1 digitaldaemon.com...
 Vathix wrote:
 Overloading an object to cast to another type:

I agree that we need something like that for symmetry. But to be used sparingly. In C++ we had explicit constructors. Maybe also opExplicitCast?
 class Another
 {
     char[] str;
     this(char[] init) { str = init; }
     void opCast(out char* result) { result = toStringz(str); }

or even, let the return type be the type to cast to. char * opCast() { return toStringz(str); }

type opExplicitCast() is a good idea
 Then i also have another idea. Some functions must be allowed to always
 implicitly cast their input, even if only explicit cast is defined for
 the input. Example:

 void sillyPrint(cast(char*) string)  { /+...+/ }

 Now, given any type, for which explicit or implicit cast is defined, it
 would be implicitly cast to char* when fed to this function.

Nope. Explicit generalisation through shims (http://www.cuj.com/documents/s=8681/cuj0308wilson/) is a far better approach. It has all of the benefits, without any of the gotchas. Matthew P.S. btw, Ilya, did I tell you that the last chapter in the book is Properties, as inspired by your good self? :)
Jan 23 2004
parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Matthew wrote:
   type opExplicitCast()
 
  is a good idea

Yup. If it doesn't complicate it for Walter too much.
Then i also have another idea. Some functions must be allowed to always
implicitly cast their input, even if only explicit cast is defined for
the input. Example:

void sillyPrint(cast(char*) string)  { /+...+/ }

Now, given any type, for which explicit or implicit cast is defined, it
would be implicitly cast to char* when fed to this function.

Nope. Explicit generalisation through shims (http://www.cuj.com/documents/s=8681/cuj0308wilson/) is a far better approach. It has all of the benefits, without any of the gotchas.

It may not be appropriate in all cases. A shim requieres explicit knowledge of the type to cast from - which may not be available for sillyPrint being a library function. I'm not sure i can recall in which case exactly it would really be very desirable, but i recall having had something on my mind a while ago... I know the conversion to char* is less than appropriate, and it was the reason why i called the function sillyPrint. ;) Luckily we have our char[], which contains length and can slice into any kind of string.
 Matthew
 
 P.S. btw, Ilya, did I tell you that the last chapter in the book is
 Properties, as inspired by your good self? :)

Yes, and it's one of the reasons i'm so eagerly awaiting the book! Btw, have you seen some Andy's experiment on the subject? http://ikagames.com/andy/property.h -eye
Jan 23 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
 Matthew wrote:
   type opExplicitCast()

  is a good idea

Yup. If it doesn't complicate it for Walter too much.

I don't see how. (But then, I'm not a compiler-writer <g>)
Then i also have another idea. Some functions must be allowed to always
implicitly cast their input, even if only explicit cast is defined for
the input. Example:

void sillyPrint(cast(char*) string)  { /+...+/ }

Now, given any type, for which explicit or implicit cast is defined, it
would be implicitly cast to char* when fed to this function.

Nope. Explicit generalisation through shims (http://www.cuj.com/documents/s=8681/cuj0308wilson/) is a far better approach. It has all of the benefits, without any of the gotchas.

It may not be appropriate in all cases. A shim requieres explicit knowledge of the type to cast from - which may not be available for sillyPrint being a library function. I'm not sure i can recall in which case exactly it would really be very desirable, but i recall having had something on my mind a while ago...

I'm not sure if we're on the same page here. A shim is used to facilitate conversion between logically related, but physically unrelated, types. For example, we can define a functor (C++) that uses the c_str_ptr() shim: template <typename C> struct path_exists { public: template <typename S> bool operator ()(S const &file) const { return exists_(c_str_ptr(file)); } private: static bool exist_(C const *file) { . . . // OS test for file existence } }; and we can use this with *any* type for which the c_str_ptr() shim is valid. In STLSoft, there are shims defined for all manner of things, so you can use the above functor in containers of BSTR, VARIANT, LSA_UNICODE_STRING, basic_string<>, char *, wchar_t*, stlsoft::basic_simple_string<>, HWND, etc. etc. The important point is that there is unlimited generality, but because it is explicit - i.e. the path_exists functor contains a call to c_str_ptr() - there are no occasions where they can be called "by mistake" by the compiler. It's basically your classic win-win (apart from the odd hassle with Koenig lookup from dimwitted compilers)
 I know the conversion to char* is less than appropriate, and it was the
 reason why i called the function sillyPrint. ;) Luckily we have our
 char[], which contains length and can slice into any kind of string.

 Matthew

 P.S. btw, Ilya, did I tell you that the last chapter in the book is
 Properties, as inspired by your good self? :)

Yes, and it's one of the reasons i'm so eagerly awaiting the book! Btw, have you seen some Andy's experiment on the subject?

Good to hear! The properties templates will be released in STLSoft 1.7.1, which should be within the next 4-5 weeks, so they'll be available a few months before the book is. Also, it's likely that there'll be at least one article in CUJ on the subject around the middle of the year, probably just a few weeks before the book is launched.
 http://ikagames.com/andy/property.h

No. I'll check it out. Does the implementation provide 100% speed efficiency, and 100% space efficiency for internally represented properties? Does it provide for field and method based properties? (Hopefully he's not stolen all my thunder <G>) Cheers Matthew P.S. I'm looking for volunteers for reviewing on the next book - taking some deep looks into STL - if anyone wants to volunteer. I understand if you don't, of course, as you may wish to save up your offers of service for the D book, which is the one after, if the current planning pans out. :)
Jan 23 2004
prev sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
 P.S. btw, Ilya, did I tell you that the last chapter in the book is
 Properties, as inspired by your good self? :)

Yes, and it's one of the reasons i'm so eagerly awaiting the book! Btw, have you seen some Andy's experiment on the subject? http://ikagames.com/andy/property.h

Hmm. It looks like this technique provides property-proxy objects, which one instantiates from a particular class instance, and which then provides property-like (get and/or set) access for the instance for which it acts. The Imperfect C++ / STLSoft properties are part of the classes for which they act; they're exactly as you'd expect from any other language which provides them as a built-in feature. (And they're stinkingly efficient! :)
Jan 23 2004
prev sibling parent reply Vathix <vathix dprogramming.com> writes:
Ilya Minkov wrote:
...
 or even, let the return type be the type to cast to.
 
     char * opCast() { return toStringz(str); }

I was going to suggest that first, but since you can't overload return values, I thought using an out parameter would be easier to implement.
Jan 23 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Vathix wrote:
     char * opCast() { return toStringz(str); }

I was going to suggest that first, but since you can't overload return values, I thought using an out parameter would be easier to implement.

Whoops! My fault. You are right. In my background, return values cannot be discarded and thus overloads on return value are feasible. ;) But in D this doesn't hold true. -eye
Jan 24 2004