digitalmars.D.learn - Aquivalent References as in C++?
- Namespace (27/27) Apr 16 2012 Hi,
- Kevin Cox (4/8) Apr 16 2012 I would recommend a precondition. It is a language enforced method of
- Timon Gehr (3/30) Apr 16 2012 You could do this:
- Namespace (10/51) Apr 16 2012 This is what I am actually doing at the moment, but I thougth
- Namespace (39/39) Apr 17 2012 Now i have something like this. It works and manipulates lvalues
- Namespace (10/49) Apr 17 2012 But if I write
- Dejan Lekic (3/57) Apr 17 2012 For that, you have static if contitions, and indeed you can make
- Namespace (3/5) Apr 17 2012 Can you show me this as code? And are there any plans to realize
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/29) Apr 17 2012 That fails because null is a compile time value and you have a special
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/7) Apr 17 2012 Scratch the 'template' part. You don't have templates there but what I
- Namespace (7/9) Apr 17 2012 Yes, but if i forget the assert i get an Access Violation error
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (54/63) Apr 17 2012 In order to get a meaningful error, the compiler would have to inject
- Namespace (4/10) Apr 17 2012 Yes, but scope is an unused storage keyword, isn't it?
- Timon Gehr (3/13) Apr 17 2012 Define 'ensure'.
- Namespace (1/2) Apr 17 2012 Guarantee, that the given object parameter isn't a null reference.
- Timon Gehr (3/5) Apr 17 2012 But C++ does not do that either.
- Namespace (1/3) Apr 17 2012 Yes, but of course only with a special Keyword/Storage class.
- Timon Gehr (2/5) Apr 17 2012 If it is not the default, how would you enforce it at the caller side?
- Namespace (8/15) Apr 17 2012 By the compiler who throws an error message or a warning.
- Namespace (3/3) Apr 17 2012 Another idea: instead scope, "in" can get a new functionality.
- bearophile (4/7) Apr 17 2012 Note that currently in D2 "in" means "scope const".
- Namespace (8/15) Apr 18 2012 Yes I know. But the importand fact is that it's only a shorthand,
- bearophile (5/7) Apr 18 2012 I have discussed this topic three or more times, and opened an enhanceme...
- bearophile (24/28) Apr 16 2012 In D struct instances are values, and you can manage them as
Hi, I have a few questions about D and could use some help. For instance, how can i rebuild such a behavior? class Foo { public: Foo(const Bar& b) { At C++ you can ensure that a reference is requested and must not null. Nevertheless lvalues are functional, which means Foo(Bar(42)) would operate just as good as Bar b(42); Foo(b); The same procedure doesn't seem to operate with const ref, instead you can only use ref. But in this case Ivalues doesn't operate. Because of the fact that in D all objects are indication of references I thought that I simply didn't need a storage class. But then I recognized that at my D equivalent… class Foo { public: this(Bar b) { …null can also be passed. That case I would like to prevent, but at the same time allow Ivalues. How does that work in D classes? As far as I know this operates with structs, but shouldn't it be possible with classes and objects too? Would be really nice if anyone had an advice for me.
Apr 16 2012
On Apr 16, 2012 5:29 PM, "Namespace" <rswhite4 googlemail.com> wrote:That case I would like to prevent, but at the same time allow Ivalues. How does that work in D classes? As far as I know this operates with structs, but shouldn't it be possible with classes and objects too?I would recommend a precondition. It is a language enforced method of restricting what values may be passed into a function. If the code is compiled for release the checks are not included and do not cost anything.
Apr 16 2012
On 04/16/2012 11:25 PM, Namespace wrote:Hi, I have a few questions about D and could use some help. For instance, how can i rebuild such a behavior? class Foo { public: Foo(const Bar& b) { At C++ you can ensure that a reference is requested and must not null. Nevertheless lvalues are functional, which means Foo(Bar(42)) would operate just as good as Bar b(42); Foo(b); The same procedure doesn't seem to operate with const ref, instead you can only use ref. But in this case Ivalues doesn't operate. Because of the fact that in D all objects are indication of references I thought that I simply didn't need a storage class. But then I recognized that at my D equivalent… class Foo { public: this(Bar b) { …null can also be passed. That case I would like to prevent, but at the same time allow Ivalues. How does that work in D classes? As far as I know this operates with structs, but shouldn't it be possible with classes and objects too? Would be really nice if anyone had an advice for me.You could do this: this(Bar b)in{assert(b !is null);}body{
Apr 16 2012
This is what I am actually doing at the moment, but I thougth that in a modern language like D, it is possible to have non-null references to avoid such constructs with assert. My last hope was that an explicit ref would allow me both: non-null references _and_ lvalues, at least for objects. That is very sad. Any possibility that this might change? I really like that objects are implicit references and so i would not use structs, but it looks like i have no choice if i would avoid asserts.. On Monday, 16 April 2012 at 21:34:34 UTC, Timon Gehr wrote:On 04/16/2012 11:25 PM, Namespace wrote:Hi, I have a few questions about D and could use some help. For instance, how can i rebuild such a behavior? class Foo { public: Foo(const Bar& b) { At C++ you can ensure that a reference is requested and must not null. Nevertheless lvalues are functional, which means Foo(Bar(42)) would operate just as good as Bar b(42); Foo(b); The same procedure doesn't seem to operate with const ref, instead you can only use ref. But in this case Ivalues doesn't operate. Because of the fact that in D all objects are indication of references I thought that I simply didn't need a storage class. But then I recognized that at my D equivalent… class Foo { public: this(Bar b) { …null can also be passed. That case I would like to prevent, but at the same time allow Ivalues. How does that work in D classes? As far as I know this operates with structs, but shouldn't it be possible with classes and objects too? Would be really nice if anyone had an advice for me.You could do this: this(Bar b)in{assert(b !is null);}body{
Apr 16 2012
Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // works
Apr 17 2012
On Tuesday, 17 April 2012 at 08:02:02 UTC, Namespace wrote:Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // worksBut if I write Bar bn; new Foo(bn); it works also and doesn't throw a compiler error. To avoid this, I have to write an assert(obj !is null); again. This really sucks. If anybody else works with my Code and puts a null reference to any method he gets no compiler error and wonder why he gets a runtime error instead. Thats very annoying...
Apr 17 2012
On Tuesday, 17 April 2012 at 09:39:10 UTC, Namespace wrote:On Tuesday, 17 April 2012 at 08:02:02 UTC, Namespace wrote:For that, you have static if contitions, and indeed you can make it a compile-time error.Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // worksBut if I write Bar bn; new Foo(bn); it works also and doesn't throw a compiler error. To avoid this, I have to write an assert(obj !is null); again. This really sucks. If anybody else works with my Code and puts a null reference to any method he gets no compiler error and wonder why he gets a runtime error instead. Thats very annoying...
Apr 17 2012
For that, you have static if contitions, and indeed you can make it a compile-time error.Can you show me this as code? And are there any plans to realize non-null references or strategies to avoid such things? Otherwise there would really be something important missing in D.
Apr 17 2012
On 04/17/2012 02:39 AM, Namespace wrote:That fails because null is a compile time value and you have a special template code for that that fails the compilation.Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler errorThere, bn is a variable that has it's own life at runtime. Although the compiler can analyze the code to determine that bn never becomes anything but null, we may not want it to be too smart. Imagine that there are lines after Bar bn; that you have just commented out: Bar bn; // bn = foo(); new Foo(bn); Now the compilation would failure would be an annoyance. That's part of the reason why the compiler does not go that deep in its analysis.new Foo(Bar(23)); // works new Foo(Bar(25)); // worksBut if I write Bar bn; new Foo(bn); it works also and doesn't throw a compiler error.To avoid this, I have to write an assert(obj !is null); again.Yes, you must because whetheer obj is null is only known at runtime.This really sucks. If anybody else works with my Code and puts a null reference to any method he gets no compiler error and wonder why he gets a runtime error instead. Thats very annoying...Ali
Apr 17 2012
On 04/17/2012 08:49 AM, Ali Çehreli wrote:That fails because null is a compile time value and you have a special template code for that that fails the compilation.Scratch the 'template' part. You don't have templates there but what I said is still valid. Basically, you have some code that fails at compile time. Ali
Apr 17 2012
Yes, you must because whetheer obj is null is only known at runtime.Yes, but if i forget the assert i get an Access Violation error with no more informations. Problem is nobody knows _why_ he gets this error, because the error message gives no information. So it must be a better solution then to write in every method "assert(obj_param !is null");". Best of all solutions would be that a special keyword, for example scope, ensure that lvalues would except but _no_ null-references.
Apr 17 2012
On 04/17/2012 10:37 AM, Namespace wrote:In order to get a meaningful error, the compiler would have to inject code that checked every access through a class reference. Unfortunately that would bring too much overhead and not be acceptable in a system language. But it could be a part of the non-release builds. I don't have any idea how slow program would become if every class dereferencing would be checked against null like that. (?)Yes, you must because whetheer obj is null is only known at runtime.Yes, but if i forget the assert i get an Access Violation error with no more informations. Problem is nobody knows _why_ he gets this error, because the error message gives no information.So it must be a better solution then to write in every method "assert(obj_param !is null");".Not in every method, but only in methods that actually dereference that pointer. Intermediate functions that simply pass the parameter to another function need not check the condition. In the end, null references are a part of D. The code must be written in a way to accept it. As an aside, enforce() may be more suitable and a little shorter: enforce(obj_param, "Even with a message"); Whether to use assert() or enforce() depends on the function.Best of all solutions would be that a special keyword, for example scope, ensure that lvalues would except but _no_ null-references.Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :) Finally, actually it is possible to have bugs of the same sort even with references in C++: // C++ code struct S { int i; S(int param_i) : i(param_i) {} }; S * make_S(int i) { return (i == 42) ? new S(i) : 0; } void use_S(const S & s) { int i = s.i; } int main() { use_S(*make_S(100)); } The output is the same as in D: Segmentation fault So, as you see, neither C++ provide any help here. C++'s references have these meanings: * On the parameter list: "I would like to have a real object please." As seen above, it is so easy to violate that. The caller of use_S() realizes that a reference is needed and just dereferences the pointer at hand. See, the caller must ensure even in C++ that the pointer that is available is not NULL. * On the return type: "What I give you is an alias to an existing object." Even this is a false promise without tool support, because the reference may be of an automatic local object. Ali
Apr 17 2012
Yes, but scope is an unused storage keyword, isn't it? So it could be an idea to avoid speed losses with the current method and ensure that the object is not null, if it's intentional.Best of all solutions would be that a special keyword, for example scope, ensure that lvalues wouldexcept but_no_ null-references.Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :)
Apr 17 2012
On 04/17/2012 08:10 PM, Namespace wrote:It is used.Yes, but scope is an unused storage keyword, isn't it?Best of all solutions would be that a special keyword, for example scope, ensure that lvalues wouldexcept but_no_ null-references.Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :)So it could be an idea to avoid speed losses with the current method and ensure that the object is not null, if it's intentional.Define 'ensure'.
Apr 17 2012
Define 'ensure'.Guarantee, that the given object parameter isn't a null reference.
Apr 17 2012
On 04/17/2012 08:40 PM, Namespace wrote:But C++ does not do that either. Are you asking for a full-blown non-null type system?Define 'ensure'.Guarantee, that the given object parameter isn't a null reference.
Apr 17 2012
But C++ does not do that either. Are you asking for a full-blown non-null type system?Yes, but of course only with a special Keyword/Storage class.
Apr 17 2012
On 04/17/2012 09:16 PM, Namespace wrote:If it is not the default, how would you enforce it at the caller side?But C++ does not do that either. Are you asking for a full-blown non-null type system?Yes, but of course only with a special Keyword/Storage class.
Apr 17 2012
On Tuesday, 17 April 2012 at 19:56:11 UTC, Timon Gehr wrote:On 04/17/2012 09:16 PM, Namespace wrote:By the compiler who throws an error message or a warning. A warning or a better error message would help also, if a null-reference was in use. But only the message "Access violation" without any information isn't enough, imo. It seems that not-null references wouldn't be a part of D in near future.If it is not the default, how would you enforce it at the caller side?But C++ does not do that either. Are you asking for a full-blown non-null type system?Yes, but of course only with a special Keyword/Storage class.
Apr 17 2012
Another idea: instead scope, "in" can get a new functionality. Instead as a synonym for "const" it could mean "not null" for objects.
Apr 17 2012
Namespace:Another idea: instead scope, "in" can get a new functionality. Instead as a synonym for "const" it could mean "not null" for objects.Note that currently in D2 "in" means "scope const". Bye, bearophile
Apr 17 2012
On Tuesday, 17 April 2012 at 23:56:12 UTC, bearophile wrote:Namespace:Yes I know. But the importand fact is that it's only a shorthand, you could use it for something more meaningful. I only want to point out how important this content is to me. Many user in other languages are wishing for a non-null reference But i think, i'm probably the only one in D who really wants something like that.Another idea: instead scope, "in" can get a new functionality. Instead as a synonym for "const" it could mean "not null" for objects.Note that currently in D2 "in" means "scope const". Bye, bearophile
Apr 18 2012
Namespace:But i think, i'm probably the only one in D who really wants something like that.I have discussed this topic three or more times, and opened an enhancement request around 2010-08-02: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Bye, bearophile
Apr 18 2012
On Wednesday, 18 April 2012 at 11:36:30 UTC, bearophile wrote:Namespace:That is incredible. What are the reasons against such implementation? I will open a new topic to discuss about that again.But i think, i'm probably the only one in D who really wants something like that.I have discussed this topic three or more times, and opened an enhancement request around 2010-08-02: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Bye, bearophile
Apr 18 2012
On Wednesday, 18 April 2012 at 11:36:30 UTC, bearophile wrote:Namespace:It really would be great to get this fixed. I do consider it "broken" right now, considering that safe is supposed to (from all the docs I've read on it) make your program incapable of using pointers incorrectly, etc. Also, the argument that C++ doesn't provide a better guarantee with references seems highly flawed, since it's deliberately using pointers to make the case that references are broken. If you make a point of using references everywhere, C++ is *MUCH* better at this.But i think, i'm probably the only one in D who really wants something like that.I have discussed this topic three or more times, and opened an enhancement request around 2010-08-02: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Bye, bearophile
Feb 22 2013
Namespace:how can i rebuild such a behavior? class Foo { public: Foo(const Bar& b) {In D struct instances are values, and you can manage them as values, or as a pointer to value (or pointer to pointer to value, etc). In D class instances are always managed by reference, and such references, like pointers, can be null (and emplace() is supposed to allow in-place allocation of a class instance). So in normal D code you can't write D code equivalent to that C++ code. Some possibilities: class Foo {} void bar(Foo f) {} void bar(const Foo f) {} struct Baz {} void spam(Baz b) {} void spam(in Baz b) {} void spam(ref Baz b) {} void spam(Baz* b) {} void spam(const Baz* b) {} void spam(const ref Baz b) {} void spam(immutable ref Baz b) {} There is also inout, out, etc. Lot of people (me too) have asked non-null class references (and pointers) in D. We are now able to disable some constructors... Bye, bearophile
Apr 16 2012