digitalmars.D.learn - Can call static method with null reference
- Namespace (19/19) Jun 20 2013 I had expected that the following code would crash:
- w0rp (6/6) Jun 20 2013 You are invoking a function effectively stored statically in a
- Jacob Carlborg (5/10) Jun 20 2013 Yeah. It's possible to call any non-virtual method without dereferencing...
- Namespace (2/2) Jun 20 2013 Yes that's obvious. My question is: is that intended? IMO this
- Jonathan M Davis (18/20) Jun 20 2013 It's a natural result of how the implementation works. Checking for null...
- Namespace (1/9) Jun 22 2013 What was the reason for this terrible design decision?
- H. S. Teoh (9/17) Jun 22 2013 I've asked about that, but never got a real answer. I'm still hoping
- monarch_dodra (16/34) Jun 22 2013 I don't see what's so terrible about it: If A can do it, I don't
- Jacob Carlborg (7/9) Jun 22 2013 The problem is that you cannot overload on "static". That is, have a two...
- Timon Gehr (3/10) Jun 22 2013 If that is the only problem then the solution is to allow overloading on...
- Jacob Carlborg (5/7) Jun 23 2013 You still need to call the static method on the class/struct if there's
- Jonathan M Davis (10/16) Jun 23 2013 I would have thought that that was obvious, and I fail to see why that w...
- Jacob Carlborg (4/12) Jun 23 2013 That's true, I didn't think of that.
- Namespace (11/12) Jun 23 2013 It's bug prone.
- Jonathan M Davis (13/28) Jun 23 2013 I fail to see what's bug-prone about that. It's confusing, but it's not
- monarch_dodra (10/47) Jun 23 2013 C++ doesn't allow it. I don't know about the rest.
- Jonathan M Davis (21/22) Jun 23 2013 Yes it does. I just tested it. This code compiles and runs just fine
- monarch_dodra (3/7) Jun 23 2013 Oh. Wow. That's news to me actually. I thought I new everything
- Jonathan M Davis (13/23) Jun 23 2013 LOL. I know a lot about C++ and _try_ to know it all, but C++ is just wa...
- Steven Schveighoffer (19/36) Jun 24 2013 I actually had a bug caused by this.
- Jonathan M Davis (6/16) Jun 24 2013 I would _love_ to make that fix, but the trick is convincing Walter (sin...
- Jesse Phillips (3/9) Jun 24 2013 Java prevents it, I'm pretty sure C# picked that up from Java.
- Jonathan M Davis (5/16) Jun 24 2013 I was certain that I'd checked it at one point and determined that Java
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
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
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
Yes that's obvious. My question is: is that intended? IMO this could cause bugs.
Jun 20 2013
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
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 DavisWhat was the reason for this terrible design decision?
Jun 22 2013
On Sat, Jun 22, 2013 at 06:34:25PM +0200, Namespace wrote: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.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 DavisWhat was the reason for this terrible design decision?
Jun 22 2013
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: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". >:(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.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 DavisWhat was the reason for this terrible design decision?
Jun 22 2013
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
On 06/22/2013 10:20 PM, Jacob Carlborg wrote:On 2013-06-22 19:11, monarch_dodra wrote:If that is the only problem then the solution is to allow overloading on static, which is easy to do.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.
Jun 22 2013
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
On Sunday, June 23, 2013 11:30:11 Jacob Carlborg wrote:On 2013-06-22 23:51, Timon Gehr 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. - Jonathan M DavisIf 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.
Jun 23 2013
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
I don't see what's so terrible about itIt'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
On Sunday, June 23, 2013 12:02:42 Namespace wrote:I fail to see what's bug-prone about that. It's confusing, but it's not causing any bugs.I don't see what's so terrible about itIt'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?It's stupid and pointless as far as I can tell, but I believe that C++, Java, 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
On Sunday, 23 June 2013 at 10:09:39 UTC, Jonathan M Davis wrote:On Sunday, June 23, 2013 12:02:42 Namespace wrote: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.I fail to see what's bug-prone about that. It's confusing, but it's not causing any bugs.I don't see what's so terrible about itIt'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?It's stupid and pointless as far as I can tell, but I believe that C++, Java, 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
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
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:Oh. Wow. That's news to me actually. I thought I new everything about C++ ^^C++ doesn't allow it. I don't know about the rest.Yes it does. - Jonathan M Davis
Jun 23 2013
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: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 DavisOn Sunday, June 23, 2013 12:48:15 monarch_dodra wrote:Oh. Wow. That's news to me actually. I thought I new everything about C++ ^^C++ doesn't allow it. I don't know about the rest.Yes it does. - Jonathan M Davis
Jun 23 2013
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: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. -SteveAlso 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, 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.
Jun 24 2013
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
On Sunday, 23 June 2013 at 10:09:39 UTC, Jonathan M Davis wrote:(Unless Java has changed since 1.5)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, stupidity
Jun 24 2013
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: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(Unless Java has changed since 1.5)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, stupidity
Jun 24 2013