www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - a couple of questions.. (mixins and inout)

reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
class A
{
 void func(){}
 template funcdecl(Type)
 {
  void func(Type t){writefln(t);}
 }
 mixin funcdecl!(int) ;
 mixin funcdecl!(float) ;
}

We all know this doesn't work but it can be fixed by adding aliases:
 mixin funcdecl!(int) a1;
 mixin funcdecl!(float) a2;
 alias a1.func func;
 alias a2.func func;

And now the name overloading works, but:
what if i want to mixin constructors, how can i do that?

 template funcdecl(Type)
 {
  this(Type t){}
 }
 mixin funcdecl!(int) a1;
 mixin funcdecl!(float) a2;
 alias a1.this this;
 alias a2.this this;

This doesn't work!

And another question:

class A{}
 void func(inout A a){}
 func(new A);
--> this doesn't work why? (new A  is not an lvalue)
If C++ can do it why not D?

It is a lot more complicated to assign temporary objects
to variables and then pass it as an inout param then to pass
it directly.
Sep 07 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 7 Sep 2004 09:07:29 +0200, Ivan Senji wrote:

 class A
 {
  void func(){}
  template funcdecl(Type)
  {
   void func(Type t){writefln(t);}
  }
  mixin funcdecl!(int) ;
  mixin funcdecl!(float) ;
 }
 
 We all know this doesn't work but it can be fixed by adding aliases:
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.func func;
  alias a2.func func;
 
 And now the name overloading works, but:
 what if i want to mixin constructors, how can i do that?
 
  template funcdecl(Type)
  {
   this(Type t){}
  }
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.this this;
  alias a2.this this;
 
 This doesn't work!
 
 And another question:
 
 class A{}
  void func(inout A a){}
  func(new A);
 --> this doesn't work why? (new A  is not an lvalue)

I assume that you are not using 'inout' because you really want to use the contents of the argument outside the function scope. Thus it fails for the same reason that ... void func(inout int a) {} func(1 + 2); fails. The argument is a temporary thing that is thrown away when the function returns. So assigning anything to it is not useful in a big-picture sense. If 'func' really *needs* to work with a temporary instance of a class, then create that inside the function, seeing you don't intend to use its contents outside of the function.
 If C++ can do it why not D?

Dunno. A mistake maybe?
 It is a lot more complicated to assign temporary objects
 to variables and then pass it as an inout param then to pass
 it directly.

I don't know why you are using inout if you don't want the contents after the function returns. I assume you don't want it because you use the idiom 'new A' as an argument value. But its more obvious to the reader of your code when they are trying to work out what you intended to happen. void func(in A a) {} func(new A); or ... void func() { A temp = new A; ...} func(); -- Derek Melbourne, Australia 7/Sep/04 5:14:36 PM
Sep 07 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:chjnsg$27n8$1 digitaldaemon.com...
 On Tue, 7 Sep 2004 09:07:29 +0200, Ivan Senji wrote:

 class A
 {
  void func(){}
  template funcdecl(Type)
  {
   void func(Type t){writefln(t);}
  }
  mixin funcdecl!(int) ;
  mixin funcdecl!(float) ;
 }

 We all know this doesn't work but it can be fixed by adding aliases:
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.func func;
  alias a2.func func;

 And now the name overloading works, but:
 what if i want to mixin constructors, how can i do that?

  template funcdecl(Type)
  {
   this(Type t){}
  }
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.this this;
  alias a2.this this;

 This doesn't work!

 And another question:

 class A{}
  void func(inout A a){}
  func(new A);
 --> this doesn't work why? (new A  is not an lvalue)

I assume that you are not using 'inout' because you really want to use the contents of the argument outside the function scope. Thus it fails for the same reason that ... void func(inout int a) {} func(1 + 2); fails.

No it is by no means the same reason. In your case you are trying to pass the adress of a temporary result of a numeric expression and that can't possibly taken, it may not even be in a memory but in a register. In my case i am passing a constructed object, living on the heap and controled by th GC. I realized that in my case i didn't really need inout, because the objects content was being changed and not the object itself, but it is quite possible that we can imagine a function that would generaly change it's argument, but we are not interested at all in the changed objects but only in the results. Let's say that for some reason my code needs inout. int num = 5; BitArray ba = new BitArray(num); setAllBits(new BitArray(ba[4..18])); i really can't imagine why i would need that object new BitArray(ba[4..18]) after the function, it is only passed to the function so that not all bits get set but only those between 4 and 18. In this example the argument need's not be inout but someone could certainly imagine an example where it was needed.
 The argument is a temporary thing that is thrown away when the function
 returns. So assigning anything to it is not useful in a big-picture sense.

No it'is not, it is an object on the heap and it is thrown away when there are no more references to it.
 If 'func' really *needs* to work with a temporary instance of a class,

 create that inside the function, seeing you don't intend to use its
 contents outside of the function.

Not an option!
 If C++ can do it why not D?

Dunno. A mistake maybe?

I wouldn't bet on it :)
 It is a lot more complicated to assign temporary objects
 to variables and then pass it as an inout param then to pass
 it directly.

I don't know why you are using inout if you don't want the contents after the function returns. I assume you don't want it because you use the idiom 'new A' as an argument value. But its more obvious to the reader of your code when they are trying to work out what you intended to happen. void func(in A a) {} func(new A); or ... void func() { A temp = new A; ...} func(); -- Derek Melbourne, Australia 7/Sep/04 5:14:36 PM

Sep 07 2004
parent Derek Parnell <derek psych.ward> writes:
On Wed, 8 Sep 2004 08:54:06 +0200, Ivan Senji wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
 news:chjnsg$27n8$1 digitaldaemon.com...
 On Tue, 7 Sep 2004 09:07:29 +0200, Ivan Senji wrote:

 class A
 {
  void func(){}
  template funcdecl(Type)
  {
   void func(Type t){writefln(t);}
  }
  mixin funcdecl!(int) ;
  mixin funcdecl!(float) ;
 }

 We all know this doesn't work but it can be fixed by adding aliases:
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.func func;
  alias a2.func func;

 And now the name overloading works, but:
 what if i want to mixin constructors, how can i do that?

  template funcdecl(Type)
  {
   this(Type t){}
  }
  mixin funcdecl!(int) a1;
  mixin funcdecl!(float) a2;
  alias a1.this this;
  alias a2.this this;

 This doesn't work!

 And another question:

 class A{}
  void func(inout A a){}
  func(new A);
 --> this doesn't work why? (new A  is not an lvalue)

I assume that you are not using 'inout' because you really want to use the contents of the argument outside the function scope. Thus it fails for the same reason that ... void func(inout int a) {} func(1 + 2); fails.

No it is by no means the same reason. In your case you are trying to pass the adress of a temporary result of a numeric expression and that can't possibly taken, it may not even be in a memory but in a register. In my case i am passing a constructed object, living on the heap and controled by th GC.

Is that how reference types work? I thought that when you pass a reference type to a function, only the reference gets passed, and thus the 'inout' qualifier effects the reference and not the actual object. Meaning that if your function is ... void func(inout A a){} the changing 'a' (rather than a's members) is permitted and your changes are passed back to the caller. So if you code func(new A); and your function changes the reference to the new object as passed, the caller will recieve your changes, but as its not assigning then to anything it will just throw them away. I suspect that is why Walter is giving you the error message. However, if your function is really changing the object's members then you can define your function as void func(in A a){} and still be allowed to modify a's members. Doing this will allow you to then code func(new A); because you are not changing the reference to the new object, just its member's. GC then kicks in as appropriate.
 I realized that in my case i didn't really need inout, because the objects
 content was being changed and not the object itself, but it is quite
 possible that we can imagine a function that would generaly change
 it's argument, but we are not interested at all in the changed objects
 but only in the results.
 
 Let's say that for some reason my code needs inout.
 
 int num = 5;
 BitArray ba = new BitArray(num);
 
 setAllBits(new BitArray(ba[4..18]));
 
 i really can't imagine why i would need that object new BitArray(ba[4..18])
 after the function, it is only passed to the function so that not all bits
 get set
 but only those between 4 and 18.
 
 In this example the argument need's not be inout but someone could
 certainly imagine an example where it was needed.

I can't imagine one. In each of these examples above, a simple 'in' qualifier is all that is needed as you are changing contents and not references. What reason would one have to create a heap object, pass a reference to it, alter the reference then throw the altered reference away? The heap object is not thrown away, just the altered reference data. -- Derek Melbourne, Australia 9/Sep/04 12:12:43 PM
Sep 08 2004