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
Permalink
Reply