January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ParticlePeter | On 01/24/2013 08:52 AM, ParticlePeter wrote: > This method here ( my first approach ) does return a reference to an > object on the heap, right ? Yes, but the caller does not get a reference. > static ref Singleton instance() { > if ( s is null ) > s = new Singleton( 0 ) ; > return * s ; > } > > so when I use it with: > auto another_s = Singleton.instance ; > > Why is the s inside the struct and another_s not identical ? > Afaik that is the purpose of the ref keyword ? When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose. import std.stdio; ref int foo() { return *new int; } void main() { auto i = foo(); writeln(typeid(i)); } Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int. Ali |
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 24 January 2013 at 17:00:44 UTC, Ali Çehreli wrote: > On 01/24/2013 08:52 AM, ParticlePeter wrote: > > > This method here ( my first approach ) does return a > reference to an > > object on the heap, right ? > > Yes, but the caller does not get a reference. Actually the caller gets the reference (which is a pointer from low-level POV), but allocates on stack struct object, and then does copy from returned reference to that stack object. > > static ref Singleton instance() { > > if ( s is null ) > > s = new Singleton( 0 ) ; > > return * s ; > > } > > > > so when I use it with: > > auto another_s = Singleton.instance ; > > > > Why is the s inside the struct and another_s not identical ? > > Afaik that is the purpose of the ref keyword ? > > When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose. > Yes, that the point - D does not have references like C++. And I should thought about C++ influence on understanding D :) > import std.stdio; > > ref int foo() > { > return *new int; > } > > void main() > { > auto i = foo(); > writeln(typeid(i)); > } > > Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int. > > Ali |
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ParticlePeter | On 01/24/13 17:52, ParticlePeter wrote:
>> Yes, but this can be broken by:
>>
>> import core.stdc.stdio : printf;
>>
>> struct Singleton {
>>
>> private :
>> this( int a = 0 ) {} ;
>> static Singleton * s ;
>>
>> public :
>> @disable this() ;
>> static Singleton* instance() {
>> if ( s is null )
>> s = new Singleton(0) ;
>> return s ;
>> }
>>
>> int val = 0 ;
>> }
>>
>> void main()
>> {
>> Singleton s = * Singleton.instance;
>> printf( "%d\n", s.val ) ; //
>> Singleton.instance.val = 2 ;
>> printf( "%d\n", s.val ) ; //0
>> }
>>
>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
>
> O.k. good to know, I'll try to avoid this. But one thing is still not clear,
> This method here ( my first approach ) does return a reference to an object on the heap, right ?
>
> static ref Singleton instance() {
> if ( s is null )
> s = new Singleton( 0 ) ;
> return * s ;
> }
>
> so when I use it with:
> auto another_s = Singleton.instance ;
>
> Why is the s inside the struct and another_s not identical ? Afaik that is the purpose of the ref keyword ?
There currently are no reference variables in D [1]; the only way to get a reference to something is via function arguments (including implicit method ones) and function returns. So assigning a ref-return means a copy.
You can workaround it like this:
struct Singleton {
private:
this( int a = 0 ) {} ;
static Singleton* s ;
public:
@disable this();
@disable this(this);
static instance() @property {
static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
if ( s is null )
s = new Singleton( 0 ) ;
return Ref!(typeof(this))(s) ;
}
int val = 0 ;
}
though, that's not how I'd do it.
artur
[1] Classes don't count; they are a reference /types/.
|
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 24 January 2013 at 17:00:44 UTC, Ali Çehreli wrote:
> On 01/24/2013 08:52 AM, ParticlePeter wrote:
>
> > This method here ( my first approach ) does return a
> reference to an
> > object on the heap, right ?
>
> Yes, but the caller does not get a reference.
>
> > static ref Singleton instance() {
> > if ( s is null )
> > s = new Singleton( 0 ) ;
> > return * s ;
> > }
> >
> > so when I use it with:
> > auto another_s = Singleton.instance ;
> >
> > Why is the s inside the struct and another_s not identical ?
> > Afaik that is the purpose of the ref keyword ?
>
> When you print the type of another_s you will see that it is not a ref, because unlike C++, D does not have local ref variables; it has pointers for that purpose.
>
> import std.stdio;
>
> ref int foo()
> {
> return *new int;
> }
>
> void main()
> {
> auto i = foo();
> writeln(typeid(i));
> }
>
> Prints 'int', not 'ref int'. So, i is a copy of the dynamically created int.
>
> Ali
Thanks, I re-read the purpose of ref type function() in the D programming language, and the sole purpose is that such a function call can be directly a parameter to another function expecting a ref ? As:
ref int foo() { return some class member ; }
void bar( ref int data ) { do something with data ; }
This means, it is never ever possible to initialize any variable with a reference some class/struct member data ? Unless I return the address of the member data ?
|
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
On 01/24/13 18:14, Artur Skawina wrote:
> struct Singleton {
> private:
> this( int a = 0 ) {} ;
> static Singleton* s ;
>
> public:
> @disable this();
> @disable this(this);
> static instance() @property {
> static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
> if ( s is null )
> s = new Singleton( 0 ) ;
> return Ref!(typeof(this))(s) ;
> }
>
> int val = 0 ;
> }
Grr. What I meant to write was of course:
static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias g this; @disable this(this); }
Sorry,
artur
|
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | On Thursday, 24 January 2013 at 17:21:38 UTC, Artur Skawina wrote:
> On 01/24/13 17:52, ParticlePeter wrote:
>>> Yes, but this can be broken by:
>>>
>>> import core.stdc.stdio : printf;
>>>
>>> struct Singleton {
>>>
>>> private :
>>> this( int a = 0 ) {} ;
>>> static Singleton * s ;
>>>
>>> public :
>>> @disable this() ;
>>> static Singleton* instance() {
>>> if ( s is null )
>>> s = new Singleton(0) ;
>>> return s ;
>>> }
>>>
>>> int val = 0 ;
>>> }
>>>
>>> void main()
>>> {
>>> Singleton s = * Singleton.instance;
>>> printf( "%d\n", s.val ) ; //
>>> Singleton.instance.val = 2 ;
>>> printf( "%d\n", s.val ) ; //0
>>> }
>>>
>>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
>>
>> O.k. good to know, I'll try to avoid this. But one thing is still not clear,
>> This method here ( my first approach ) does return a reference to an object on the heap, right ?
>>
>> static ref Singleton instance() {
>> if ( s is null )
>> s = new Singleton( 0 ) ;
>> return * s ;
>> }
>>
>> so when I use it with:
>> auto another_s = Singleton.instance ;
>>
>> Why is the s inside the struct and another_s not identical ?
>> Afaik that is the purpose of the ref keyword ?
>
> There currently are no reference variables in D [1]; the only way to get
> a reference to something is via function arguments (including implicit
> method ones) and function returns. So assigning a ref-return means a copy.
>
> You can workaround it like this:
>
> struct Singleton {
> private:
> this( int a = 0 ) {} ;
> static Singleton* s ;
>
> public:
> @disable this();
> @disable this(this);
> static instance() @property {
> static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias obj this; @disable this(this); }
> if ( s is null )
> s = new Singleton( 0 ) ;
> return Ref!(typeof(this))(s) ;
> }
>
> int val = 0 ;
> }
>
> though, that's not how I'd do it.
>
> artur
>
> [1] Classes don't count; they are a reference /types/.
Well ... I think I as well would not wanna do it like this, thanks :-)
I'm fine with returning and using a pointer, fortunately there is no difference in syntax as in c, so it doesn't matter.
|
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ParticlePeter | On 01/24/2013 09:26 AM, ParticlePeter wrote: > Thanks, I re-read the purpose of ref type function() in the D > programming language, and the sole purpose is that such a function call > can be directly a parameter to another function expecting a ref ? As Maxim Fomin noted, I didn't word it correctly: The caller does get a reference to the returned object. So, the sole purpose is not to pass a variable to a ref-taking function. > As: > > ref int foo() { return some class member ; } > void bar( ref int data ) { do something with data ; } > > This means, it is never ever possible to initialize any variable with a > reference some class/struct member data ? Unless I return the address of > the member data ? Not true. There are no local ref variables nor ref member variables in D. All you need to do is to use pointers instead: ref int foo() { return *new int; } struct S { int i; int * j; this(int i) { this.i = i; this.j = &foo(); // member pointer } } void main() { int* i = &foo(); // local pointer } No, the pointer syntax is not the cleanest. :) Ali |
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ParticlePeter | On 01/24/2013 09:35 AM, ParticlePeter wrote: > I'm fine with returning and using a pointer, fortunately there is no > difference in syntax as in c, so it doesn't matter. With the exception that the -> operator is replaced by the dot operator in D: MyStruct * p = /* ... */; // Dot, not -> p.foo(); p.i = 42; Ali |
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to ParticlePeter | On 01/24/13 18:35, ParticlePeter wrote: > On Thursday, 24 January 2013 at 17:21:38 UTC, Artur Skawina wrote: >> On 01/24/13 17:52, ParticlePeter wrote: >>> Why is the s inside the struct and another_s not identical ? Afaik that is the purpose of the ref keyword ? >> >> There currently are no reference variables in D [1]; the only way to get a reference to something is via function arguments (including implicit method ones) and function returns. So assigning a ref-return means a copy. >> >> You can workaround it like this: >> >> struct Singleton { >> private: >> this( int a = 0 ) {} ; >> static Singleton* s ; >> >> public: >> @disable this(); >> @disable this(this); >> static instance() @property { >> static struct Ref(T) { T* obj; ref g() @property { return *obj; } alias g this; @disable this(this); } >> if ( s is null ) >> s = new Singleton( 0 ) ; >> return Ref!(typeof(this))(s) ; >> } >> >> int val = 0 ; >> } > Well ... I think I as well would not wanna do it like this, thanks :-) > I'm fine with returning and using a pointer, fortunately there is no difference in syntax as in c, so it doesn't matter. Careful, at some point you'll end up doing s[1] etc, and /then/ it matters. The Ref struct is actually the way to deal with "ref" types in D; what I meant by 'that's not how I'd do it' is that it might be better to use a global (well, thread-local module-field in D) etc. artur |
January 24, 2013 Re: Singleton Pattern with struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 24 January 2013 at 17:35:58 UTC, Ali Çehreli wrote:
> On 01/24/2013 09:26 AM, ParticlePeter wrote:
>
> > Thanks, I re-read the purpose of ref type function() in the D
> > programming language, and the sole purpose is that such a
> function call
> > can be directly a parameter to another function expecting a
> ref ?
>
> As Maxim Fomin noted, I didn't word it correctly: The caller does get a reference to the returned object.
>
> So, the sole purpose is not to pass a variable to a ref-taking function.
>
> > As:
> >
> > ref int foo() { return some class member ; }
> > void bar( ref int data ) { do something with data ; }
> >
> > This means, it is never ever possible to initialize any
> variable with a
> > reference some class/struct member data ? Unless I return the
> address of
> > the member data ?
>
> Not true. There are no local ref variables nor ref member variables in D. All you need to do is to use pointers instead:
>
> ref int foo()
> {
> return *new int;
> }
>
> struct S
> {
> int i;
> int * j;
>
> this(int i)
> {
> this.i = i;
> this.j = &foo(); // member pointer
> }
> }
>
> void main()
> {
> int* i = &foo(); // local pointer
> }
>
> No, the pointer syntax is not the cleanest. :)
>
> Ali
This is what I meant :-) I can't return a reference ( with reference I don't mean reference type, but semantically a reference ) to a class member, but I can return the address of this member, which, to my understanding is an implicit pointer.
struct Foo {
int val = 3 ;
auto getValPtr() { return & val ; }
}
Foo foo ;
writeln( foo.val ) ; // = 3
auto valPtr = foo.getValPtr() ;
* valPtr = 7 ;
writeln( foo.val ) ; // = 7
|
Copyright © 1999-2021 by the D Language Foundation