| Thread overview | ||||||||
|---|---|---|---|---|---|---|---|---|
|
May 06, 2007 Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Why is this illegal in D? As I understand it (from discussion with GregorR on IRC), methods of a D struct are not virtual --- the following program cannot use vtables as an excuse for its AssertError.
struct foo {
int doit(int x) { return 42; }
}
void main() {
foo *bar; bar.doit(9);
}
Neither does the following slightly less trivial code (note that null pointers passed as the 'this' argument aren't dereferenced by struct list's methods):
struct list {
list *next;
int data;
static list *make(list *foo, int bar) {
list *x = new list();
x.next = foo; x.data = bar;
return x;
}
list *put(int k) {
return make(this, k);
}
bool has(int k) {
if (this == null) return false;
return data == k || next.has(k);
}
}
void main() {
list *foo;
foo = foo.put(42);
foo = foo.put(17);
foo = foo.put(31345);
assert(foo.has(42));
assert(foo.has(17));
assert(foo.has(31345));
assert(!foo.has(24));
}
(Except for one minor detail about foo not being initialised to null by default, this is perfectly good C++ code; calling a nonvirtual method of a null pointer-to-struct simply results in the 'this' parameter coming out to be null. So, like, why doesn't D do the same?)
Tor Myklebust
| ||||
May 06, 2007 Re: Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tor Myklebust | Tor Myklebust wrote: > Why is this illegal in D? As I understand it (from discussion with GregorR on IRC), methods of a D struct are not virtual --- the following program cannot use vtables as an excuse for its AssertError. [snip] > (Except for one minor detail about foo not being initialised to null by default, this is perfectly good C++ code; calling a nonvirtual method of a null pointer-to-struct simply results in the 'this' parameter coming out to be null. So, like, why doesn't D do the same?) It's technically invalid in C++ also unless the function is a static member function. The fact that most compilers allow it to run means nothing; in a portably valid C++ program, the value of the "this" pointer is never null. If D requires this to be diagnosed in at least some modes, that would be a minor improvement on C++ (which leaves this as undefined, largely for performance reasons). -- James | |||
May 06, 2007 Re: Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Posted in reply to James Dennett | James Dennett <jdennett@acm.org> wrote:
> Tor Myklebust wrote:
> > Why is this illegal in D? As I understand it (from discussion with GregorR on IRC), methods of a D struct are not virtual --- the following program cannot use vtables as an excuse for its AssertError.
>
> [snip]
>
> > (Except for one minor detail about foo not being initialised to null by default, this is perfectly good C++ code; calling a nonvirtual method of a null pointer-to-struct simply results in the 'this' parameter coming out to be null. So, like, why doesn't D do the same?)
>
> It's technically invalid in C++ also unless the function
> is a static member function. The fact that most compilers
> allow it to run means nothing; in a portably valid C++
> program, the value of the "this" pointer is never null.
>
> If D requires this to be diagnosed in at least some modes,
> that would be a minor improvement on C++ (which leaves
> this as undefined, largely for performance reasons).
OK, what you say about the C++ standard is true; 9.3.2.1 says the this pointer is a pointer to the object on which the function is called, and there can't very well be such a thing if this is null. (I still see no earthly reason why it *should* be invalid for nonvirtual functions --- by extension, I see no earthly reason why it should be invalid for methods in D structs.)
Tor Myklebust
| |||
May 06, 2007 Re: Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tor Myklebust | Reply to Tor, > Why is this illegal in D? As I understand it (from discussion with > GregorR on IRC), methods of a D struct are not virtual --- the > following program cannot use vtables as an excuse for its AssertError. > > struct foo { > int doit(int x) { return 42; } > } > void main() { > foo *bar; bar.doit(9); > } try this > foo *bar= cast(foo*)(null+1); bar.doit(9); I was found this trick because I had a function that needed to be called as a delegate and I didn't want the overhead of doing the nested call trick. p.s. Wow, 2 (strange things I was working on that other people bring up) in one day! The other is label variables. | |||
May 06, 2007 Re: Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tor Myklebust | Tor Myklebust wrote: > [...] (I still see no > earthly reason why it *should* be invalid for nonvirtual functions --- > by extension, I see no earthly reason why it should be invalid for > methods in D structs.) > > Tor Myklebust I suppose one could argue that if it is allowable to call the method with a non-existent instance for context, then there's no reason for making it a member function in the first place. Conversely, the vast majority of member functions are member functions specifically *because* they require the context to be there, where the assertion makes sense to have. Of course, since all D ever gives is "ZOMG! ASSERT ERRORZ!" and neither tells you *where* it happened[1], or on what, it's not very useful for more than telling you you screwed up somewhere. Thank $DEITY for ddbg, though. -- Daniel [1] Ok, it tells you the line of the function being called, but all things considered, that isn't very useful. Oh for the day we get back-traces in the standard library :) -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ | |||
May 07, 2007 Re: Calling members of null pointers-to-struct | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep <daniel.keep.lists@gmail.com> wrote:
>
>
> Tor Myklebust wrote:
> > [...] (I still see no
> > earthly reason why it *should* be invalid for nonvirtual functions ---
> > by extension, I see no earthly reason why it should be invalid for
> > methods in D structs.)
> >
> > Tor Myklebust
>
> I suppose one could argue that if it is allowable to call the method with a non-existent instance for context, then there's no reason for making it a member function in the first place.
>
> Conversely, the vast majority of member functions are member functions specifically *because* they require the context to be there, where the assertion makes sense to have.
It doesn't make sense, though, which was precisely the point of the original post. I even gave an example demonstrating why it doesn't make sense; it is reproduced below:
struct list {
list *next;
int data;
static list *make(list *foo, int bar) {
list *x = new list();
x.next = foo; x.data = bar;
return x;
}
list *put(int k) {
return make(this, k);
}
bool has(int k) {
if (this == null) return false;
return data == k || next.has(k);
}
}
void main() {
list *foo;
foo = foo.put(42);
foo = foo.put(17);
foo = foo.put(31345);
assert(foo.has(42));
assert(foo.has(17));
assert(foo.has(31345));
assert(!foo.has(24));
}
This is a toy implementation of a linked list representing a set of ints. The empty list is represented by a null pointer. A nonempty list is represented by a null-terminated, er, list of struct lists.
It makes sense for put() to be a member function because put() needs to know what 'this' is. It doesn't need to know about any of the members of 'this', though, so it doesn't need to dereference 'this'. It also makes sense for 'has' to be a member function, since it needs to know about 'data' and 'has'. (Neither one is needed if 'this' is null, however, since null represents the empty list and the empty list contains nothing.) Thus, in neither method does it make sense for a not-null assertion to be made but in both methods the context provided by 'this' is required.
Tor Myklebust
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply