www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can call static method with null reference

reply "Namespace" <rswhite4 googlemail.com> writes:
I had expected that the following code would crash:
It it intended?

----
import std.stdio;

class Foo {
public:
	static void test1() { }
	void test2() { }
}

void main()
{
	Foo.test1();
	/// Foo.test2(); crash as expected
	
	Foo f;
	f.test1(); /// works o.O - should crash?
	/// f.test2(); also crash - null pointer
}
----
Jun 20 2013
parent reply "w0rp" <devw0rp gmail.com> writes:
You are invoking a function effectively stored statically in a 
class namespace. So you never actually dereference the null 
reference. You're just calling a function that doesn't really 
have anything to do with the reference. I prefer to tell it like 
it is and call the static method with the class name, so in this 
case that would be Foo.test1.
Jun 20 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-06-20 21:17, w0rp wrote:
 You are invoking a function effectively stored statically in a class
 namespace. So you never actually dereference the null reference. You're
 just calling a function that doesn't really have anything to do with the
 reference. I prefer to tell it like it is and call the static method
 with the class name, so in this case that would be Foo.test1.
Yeah. It's possible to call any non-virtual method without dereferencing a null reference. -- /Jacob Carlborg
Jun 20 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
Yes that's obvious. My question is: is that intended? IMO this 
could cause bugs.
Jun 20 2013
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, June 20, 2013 21:38:57 Namespace wrote:
 Yes that's obvious. My question is: is that intended? IMO this
 could cause bugs.
It's a natural result of how the implementation works. Checking for null would just be extra overhead (Walter won't even do that for virtual functions which _will_ blow up when you call them on null references). And you'll get a segfault as soon as you actually use a member variable or virtual function with a null reference within a non-virtual function. So, I don't see why it would be a problem other than the fact that it's potentially confusing to people when they see a null this reference, since most people don't think that's possible. And there's _definitely_ no point in checking if you're calling a static function. The only possible bug that you have there is if thought that you were calling a member function rather than a static function and that caused you to misunderstand what the code was doing and potentially write buggy stuff around it - but that's a problem caused by the fact that static functions can be called via an instance, and fixing that would mean making it illegal to call static functions on instances (which I would love to have happen but don't expect to ever happen). - Jonathan M Davis
Jun 20 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
 but that's a problem caused by the fact that static functions 
 can
 be called via an instance, and fixing that would mean making it 
 illegal to call
 static functions on instances (which I would love to have 
 happen but don't
 expect to ever happen).

 - Jonathan M Davis
What was the reason for this terrible design decision?
Jun 22 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Jun 22, 2013 at 06:34:25PM +0200, Namespace wrote:
but that's a problem caused by the fact that static functions can be
called via an instance, and fixing that would mean making it illegal
to call static functions on instances (which I would love to have
happen but don't expect to ever happen).

- Jonathan M Davis
What was the reason for this terrible design decision?
I've asked about that, but never got a real answer. I'm still hoping people would change their mind and reverse this bad decision. Conflating static members with non-static members is just a really bad idea. T -- "640K ought to be enough" -- Bill G., 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.
Jun 22 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Saturday, 22 June 2013 at 16:44:36 UTC, H. S. Teoh wrote:
 On Sat, Jun 22, 2013 at 06:34:25PM +0200, Namespace wrote:
but that's a problem caused by the fact that static functions 
can be
called via an instance, and fixing that would mean making it 
illegal
to call static functions on instances (which I would love to 
have
happen but don't expect to ever happen).

- Jonathan M Davis
What was the reason for this terrible design decision?
I've asked about that, but never got a real answer. I'm still hoping people would change their mind and reverse this bad decision. Conflating static members with non-static members is just a really bad idea.
I don't see what's so terrible about it: If A can do it, I don't see what an instance of a couldn't? I find that it is in line with what ufcs does: It streamlines the calling convention. This is particularly relevent to the fact that D has a lot of emphasis on "auto" type, which means that more often than not, it is easy to manipulate the instance, but more laborious to get the type. EG: auto myObject = foo!"mode".getObject(); auto copy = myObject[0].bar.CreateInstance(); There! I wouldn't want to have to insert a typeof in there. My bar member is perfectly capable of creating and instance, so I don't see why I'd have to explicitly request this from the typeof. ... unless typeof could be used ufcs style, as a property, just like stringof et al. ... *THEN* we'd be talking. I *HATE* writing "typeof(a).stringof" or whatever when everything screams at me to write "a.typeof.stringof". >:(
Jun 22 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-06-22 19:11, monarch_dodra wrote:

 I don't see what's so terrible about it: If A can do it, I don't see
 what an instance of a couldn't?
The problem is that you cannot overload on "static". That is, have a two methods with the same name, one being declared "static". Usually it's possible to find a different name for one of the methods to avoid overloading. That's not always the case though, for example, opDispatch. -- /Jacob Carlborg
Jun 22 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/22/2013 10:20 PM, Jacob Carlborg wrote:
 On 2013-06-22 19:11, monarch_dodra wrote:

 I don't see what's so terrible about it: If A can do it, I don't see
 what an instance of a couldn't?
The problem is that you cannot overload on "static". That is, have a two methods with the same name, one being declared "static". Usually it's possible to find a different name for one of the methods to avoid overloading. That's not always the case though, for example, opDispatch.
If that is the only problem then the solution is to allow overloading on static, which is easy to do.
Jun 22 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-06-22 23:51, Timon Gehr wrote:

 If that is the only problem then the solution is to allow overloading on
 static, which is easy to do.
You still need to call the static method on the class/struct if there's an ambiguity. -- /Jacob Carlborg
Jun 23 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, June 23, 2013 11:30:11 Jacob Carlborg wrote:
 On 2013-06-22 23:51, Timon Gehr wrote:
 If that is the only problem then the solution is to allow overloading on
 static, which is easy to do.
You still need to call the static method on the class/struct if there's an ambiguity.
I would have thought that that was obvious, and I fail to see why that would be a problem. The only risk I see in allowing static and non-static functions to be overloaded, is that if you have static function being called with an instance, and you add a non-static overload, then the code would silently change to call the non-static function. But we have that exact same problem with UFCS and member functions as it is, and that wouldn't break any existing code (since you can't overload on static right now). It would just be a future risk of breaking code. - Jonathan M Davis
Jun 23 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-06-23 12:04, Jonathan M Davis wrote:

 I would have thought that that was obvious, and I fail to see why that would
 be a problem. The only risk I see in allowing static and non-static functions
 to be overloaded, is that if you have static function being called with an
 instance, and you add a non-static overload, then the code would silently
 change to call the non-static function. But we have that exact same problem
 with UFCS and member functions as it is, and that wouldn't break any existing
 code (since you can't overload on static right now). It would just be a future
 risk of breaking code.
That's true, I didn't think of that. -- /Jacob Carlborg
Jun 23 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
 I don't see what's so terrible about it
It's bug prone. class Foo { public: static void test1() { } void test2() { } } Foo f; f.test1(); /// Oh nice, that works, f is not null. f.test2(); /// WTF? f is null? Also I don't know why I should call static methods from an instance. What's the purpose?
Jun 23 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, June 23, 2013 12:02:42 Namespace wrote:
 I don't see what's so terrible about it
It's bug prone. class Foo { public: static void test1() { } void test2() { } } Foo f; f.test1(); /// Oh nice, that works, f is not null. f.test2(); /// WTF? f is null?
I fail to see what's bug-prone about that. It's confusing, but it's not causing any bugs.
 Also I don't know why I should call static methods from an
 instance. What's the purpose?
It's stupid and pointless as far as I can tell, but I believe that C++, Java, C#, and D all do it, so as stupid as it is, it's a common stupidity. I certainly wish that we could change it, but I wouldn't expect Walter to agree to the change, since it would break at least some existing code, and I suspect that he doesn't consider the fact that you can call static functions on instances to be a problem. That's not the sort of thing that he generally seems to think is an issue. It's almost always stuff that causes actual bugs that he agrees to change and not things that are aesthetically displeasing or which could theoretically cause bugs. - Jonathan M Davis
Jun 23 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 23 June 2013 at 10:09:39 UTC, Jonathan M Davis wrote:
 On Sunday, June 23, 2013 12:02:42 Namespace wrote:
 I don't see what's so terrible about it
It's bug prone. class Foo { public: static void test1() { } void test2() { } } Foo f; f.test1(); /// Oh nice, that works, f is not null. f.test2(); /// WTF? f is null?
I fail to see what's bug-prone about that. It's confusing, but it's not causing any bugs.
 Also I don't know why I should call static methods from an
 instance. What's the purpose?
It's stupid and pointless as far as I can tell, but I believe that C++, Java, C#, and D all do it, so as stupid as it is, it's a common stupidity. I certainly wish that we could change it, but I wouldn't expect Walter to agree to the change, since it would break at least some existing code, and I suspect that he doesn't consider the fact that you can call static functions on instances to be a problem. That's not the sort of thing that he generally seems to think is an issue. It's almost always stuff that causes actual bugs that he agrees to change and not things that are aesthetically displeasing or which could theoretically cause bugs. - Jonathan M Davis
C++ doesn't allow it. I don't know about the rest. If anything, I find overloading static non static could make sense: A.print(); //"I'm an A!" a.print(); //"I'm an A called foo!" With this in mind, it can mean that a struct can first define the static function, and in the future, add extra logic to handle information from a specific instance, yet without having to caller code.
Jun 23 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, June 23, 2013 12:48:15 monarch_dodra wrote:
 C++ doesn't allow it. I don't know about the rest.
Yes it does. I just tested it. This code compiles and runs just fine #include <iostream> using namespace std; class C { public: static void foo() { cout << "I'm static!" << endl; } }; int main() { C c; c.foo(); return 0; } And just like D, C++ won't allow you to overload on static (also just tested), so D's behavior in this regard appears to be identical to C++. - Jonathan M Davis
Jun 23 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 23 June 2013 at 10:59:06 UTC, Jonathan M Davis wrote:
 On Sunday, June 23, 2013 12:48:15 monarch_dodra wrote:
 C++ doesn't allow it. I don't know about the rest.
Yes it does. - Jonathan M Davis
Oh. Wow. That's news to me actually. I thought I new everything about C++ ^^
Jun 23 2013
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, June 23, 2013 13:35:55 monarch_dodra wrote:
 On Sunday, 23 June 2013 at 10:59:06 UTC, Jonathan M Davis wrote:
 On Sunday, June 23, 2013 12:48:15 monarch_dodra wrote:
 C++ doesn't allow it. I don't know about the rest.
Yes it does. - Jonathan M Davis
Oh. Wow. That's news to me actually. I thought I new everything about C++ ^^
LOL. I know a lot about C++ and _try_ to know it all, but C++ is just way too complicated for that (at least for me). Even if I learn all of the stray esoteric stuff, I can't retain it all. There's just too much of it. With D, I feel like I _might_ be able to do it. I definitely don't know everything that there is to know about D, and I don't always remember all of the little details that I learn (plus some of them change over time), but I do a much better job of remembering it. It doesn't have anywhere near as many dark corners to it, and so in spite of its complexity, it at least feels like it could all be understood and remembered by one person (unlike C++). So, _maybe_ someday I'll be able to claim that I know the D language through and through, but I'll definitely _never_ be able to claim that with C++. - Jonathan M Davis
Jun 23 2013
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 23 Jun 2013 06:09:19 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Sunday, June 23, 2013 12:02:42 Namespace wrote:
 Also I don't know why I should call static methods from an
 instance. What's the purpose?
It's stupid and pointless as far as I can tell, but I believe that C++, Java, C#, and D all do it, so as stupid as it is, it's a common stupidity. I certainly wish that we could change it, but I wouldn't expect Walter to agree to the change, since it would break at least some existing code, and I suspect that he doesn't consider the fact that you can call static functions on instances to be a problem. That's not the sort of thing that he generally seems to think is an issue. It's almost always stuff that causes actual bugs that he agrees to change and not things that are aesthetically displeasing or which could theoretically cause bugs.
I actually had a bug caused by this. But the reason is simply duck typing. For example: class InfiniteRange { ... static bool empty() { return false; } } My suggestion to fix this has always been: only allow static calls on instance variables via opt-in. e.g.: class InfiniteRange { static bool empty() { return false; } alias InfiniteRange.empty this.empty; // just an example } This allows all the benefit, but none of the bug-prone problems. -Steve
Jun 24 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, June 24, 2013 11:51:52 Steven Schveighoffer wrote:
 My suggestion to fix this has always been: only allow static calls on
 instance variables via opt-in. e.g.:
 
 class InfiniteRange
 {
 static bool empty() { return false; }
 alias InfiniteRange.empty this.empty; // just an example
 }
 
 This allows all the benefit, but none of the bug-prone problems.
I would _love_ to make that fix, but the trick is convincing Walter (since the chance risks breaking code). Or maybe it's one of those things that convincing Kenji to implement it would be enough, since it could sneak in that way? I don't know. Regardless, I think that we'd be better off if we made the change. - Jonathan M Davis
Jun 24 2013
prev sibling parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Sunday, 23 June 2013 at 10:09:39 UTC, Jonathan M Davis wrote:
 Also I don't know why I should call static methods from an
 instance. What's the purpose?
It's stupid and pointless as far as I can tell, but I believe that C++, Java, C#, and D all do it, so as stupid as it is, it's a common stupidity
Java prevents it, I'm pretty sure C# picked that up from Java. (Unless Java has changed since 1.5)
Jun 24 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, June 24, 2013 19:13:45 Jesse Phillips wrote:
 On Sunday, 23 June 2013 at 10:09:39 UTC, Jonathan M Davis wrote:
 Also I don't know why I should call static methods from an
 instance. What's the purpose?
It's stupid and pointless as far as I can tell, but I believe that C++, Java, C#, and D all do it, so as stupid as it is, it's a common stupidity
Java prevents it, I'm pretty sure C# picked that up from Java. (Unless Java has changed since 1.5)
I was certain that I'd checked it at one point and determined that Java allowed it, but I could be wrong. It's certainly better if I am, since it's a bad design decision to allow static functions to be called on instances IMHO. - Jonathan M Davis
Jun 24 2013