Jump to page: 1 2 3
Thread overview
Aquivalent References as in C++?
Apr 16, 2012
Namespace
Apr 16, 2012
Kevin Cox
Apr 16, 2012
Timon Gehr
Apr 16, 2012
Namespace
Apr 17, 2012
Namespace
Apr 17, 2012
Namespace
Apr 17, 2012
Dejan Lekic
Apr 17, 2012
Namespace
Apr 17, 2012
Ali Çehreli
Apr 17, 2012
Ali Çehreli
Apr 17, 2012
Namespace
Apr 17, 2012
Ali Çehreli
Apr 17, 2012
Namespace
Apr 17, 2012
Timon Gehr
Apr 17, 2012
Namespace
Apr 17, 2012
Timon Gehr
Apr 17, 2012
Namespace
Apr 17, 2012
Timon Gehr
Apr 17, 2012
Namespace
Apr 17, 2012
Namespace
Apr 17, 2012
bearophile
Apr 18, 2012
Namespace
Apr 18, 2012
bearophile
Apr 18, 2012
Namespace
Feb 22, 2013
Lee
Apr 16, 2012
bearophile
April 16, 2012
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.
April 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.


April 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{
April 16, 2012
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
April 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{


April 17, 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
April 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)); // works


But 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...
April 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:
>> 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
>
>
> But 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...

For that, you have static if contitions, and indeed you can make it a compile-time error.
April 17, 2012
On 04/17/2012 02:39 AM, Namespace wrote:

>> Bar b = new Bar(42);
>>
>> new Foo(b); // works
>> new Foo(null); // compiler error

That fails because null is a compile time value and you have a special template code for that that fails the compilation.

>> new Foo(Bar(23)); // works
>> new Foo(Bar(25)); // works
>
>
> But if I write
>
> Bar bn;
> new Foo(bn);
>
> it works also and doesn't throw a compiler error.

There, 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.

> 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

April 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

« First   ‹ Prev
1 2 3