Re: inheriting ctors?

2010-08-06 Thread Andrej Mitrovic
Here's an example:

import std.stdio;
import std.traits;
import std.conv;
import std.typecons;

class C
{
int m_value;

int testMe()
{
return 1;
}

this(int x) 
{ 
m_value = x; 
}

this(int x, int z)
{
m_value = x + z;
}
}

template inheritClassMethods(Base)
{
alias AutoImplement!(Base, generateEmptyFunction, isAbstractFunction) 
inheritClassMethods;
}

void main()
{
auto c = new inheritClassMethods!C(42, 56);
} 

So basically you can instantiate a highly modified class that's based on 
another class at compile time. You can change the method definitions, and even 
leave some out. What's really cool about this is that you can, say, add logging 
ability to all methods of a class without having to manually add them in class 
definition (there's an example in the docs). Which could be quite useful in 
debugging I suposse.

isAbstractFunction and generateEmptyFunction are from std.typecons (I think), 
but you can pass your own template functions instead of these.

I'm just getting a lot of errors because it seems very sensitive to what kind 
of functions you're going to inherit.. well it's complicated. And there's some 
warnings about bugs in the sources. Still, I like the premise of AutoImplement.

Andrej Mitrovic Wrote:

> There is an AutoImplement class template in 
> http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#AutoImplement , 
> which I've just been trying out. Apparently you can pass it 1: a Base class, 
> 2: a templated function to filter out which functions you want to 
> inherit/overwrite from the Base class, and 3: a template function which can 
> re-write the bodies of each function which is not filtered out (+ there are 
> some "macros" which you can use to quickly access the functions' parameters 
> and other such things).
> 
> But it's a mess to work with, and I'm not sure how I'm supossed to use it if 
> I'm trying to do something like "class B : A".., because it looks like 
> AutoImplement creates a class and instantiates it, it doesn't return a string 
> ready to be mixed in like you are doing in your example.
> 
> There's an example of BlackBox and WhiteBox, which use AutoImplement, on the 
> same page. Maybe you guys could make sense of it, it's too hard for me atm. 
> (D newbie)
> 
> // Offtopic
> Template errors are so hard to grasp, most of the time it's best to just 
> ignore them and take some logical steps to fix the errors. At least that's in 
> my case true..
> 
> Rory Mcguire Wrote:
> 
> > Rory Mcguire wrote:
> > 
> > > Philippe Sigaud wrote:
> > > 
> > >> On Fri, Aug 6, 2010 at 11:43, Rory Mcguire 
> > >> wrote:
> > >> 
> > >> 
> > >>> I've been trying to make a template for this but it seems that dmd still
> > >>> won't allow me to get the parameters of the constructors. dmd Seems to
> > >>> think
> > >>> that I'm trying to use it as a property.
> > >>>
> > >>>
> > >> 
> > >>> void main() {
> > >>>foreach (m; __traits(getOverloads, A, "__ctor")) {
> > >>>pragma(msg, m.stringof); // it thinks I'm calling m
> > >>>}
> > >>> }
> > >>>
> > >>> constructors.d(34): Error: constructor constructors.A.this (int x) is
> > >>> not callable using argument types ()
> > >>>
> > >> 
> > >> This is my new once-a-day bug :(
> > >> Using a function alias, and being unable to call properties on it,
> > >> because DMD thinks I'm calling it. Man, it's no property, just a name!
> > >> 
> > >> Anyway, just pragma(msg, m) works, strangely.
> > >> I think I found a way to use m, somewhat:
> > >> 
> > >> void main() {
> > >>foreach (m; __traits(getOverloads, A, "__ctor")) {
> > >>pragma(msg, m); // it thinks I'm calling m
> > >>typeof(&m) tmp = &m;
> > >> writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double),
> > >> (string)
> > >> writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int)
> > >> writeln( typeof(&m).stringof); // A function(int x), A
> > >> function(double x), A function(string s)
> > >>}
> > >> }
> > >> 
> > >> using ParameterTypeTuple!m directly does not differentiate the m's. But
> > >> using a temporary pointer, it seems to work.
> > >> 
> > >> Oh and I even get the arguments names !
> > >> 
> > >> 
> > >> Philippe
> > > 
> > > Thanks!! works now. Now we just need to be able to select which
> > > constructors we actually want.
> > > 
> > > string inheritconstructors_helper(alias T)() {
> > > string s;
> > > foreach (m; __traits(getOverloads, T, "__ctor")) {
> > > string args, args1;
> > > foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
> > > pragma(msg, cons.stringof);
> > > args ~= ","~cons.stringof~" v"~to!string(i);
> > > args1 ~= ",v"~to!string(i);
> > > }
> > > args = args.length < 1 ? args : args[1..$];
> > > args1 = args1.length < 1 ? args1 : args1[1..$];
> > > s ~= "this("~args~") { super("~args1~"); }\n";
>

Re: Operator overloading problem

2010-08-06 Thread Blonder
Thanks, that is the solution.

> No programming language is intuitive; they all take time to learn.
> D is a big win over C++ though and well worth sticking with.

Yes, you are right, it takes time to learn.

@Philippe Sigaud
Thanks also.


Re: inheriting ctors?

2010-08-06 Thread Andrej Mitrovic
There is an AutoImplement class template in 
http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#AutoImplement , which 
I've just been trying out. Apparently you can pass it 1: a Base class, 2: a 
templated function to filter out which functions you want to inherit/overwrite 
from the Base class, and 3: a template function which can re-write the bodies 
of each function which is not filtered out (+ there are some "macros" which you 
can use to quickly access the functions' parameters and other such things).

But it's a mess to work with, and I'm not sure how I'm supossed to use it if 
I'm trying to do something like "class B : A".., because it looks like 
AutoImplement creates a class and instantiates it, it doesn't return a string 
ready to be mixed in like you are doing in your example.

There's an example of BlackBox and WhiteBox, which use AutoImplement, on the 
same page. Maybe you guys could make sense of it, it's too hard for me atm. (D 
newbie)

// Offtopic
Template errors are so hard to grasp, most of the time it's best to just ignore 
them and take some logical steps to fix the errors. At least that's in my case 
true..

Rory Mcguire Wrote:

> Rory Mcguire wrote:
> 
> > Philippe Sigaud wrote:
> > 
> >> On Fri, Aug 6, 2010 at 11:43, Rory Mcguire 
> >> wrote:
> >> 
> >> 
> >>> I've been trying to make a template for this but it seems that dmd still
> >>> won't allow me to get the parameters of the constructors. dmd Seems to
> >>> think
> >>> that I'm trying to use it as a property.
> >>>
> >>>
> >> 
> >>> void main() {
> >>>foreach (m; __traits(getOverloads, A, "__ctor")) {
> >>>pragma(msg, m.stringof); // it thinks I'm calling m
> >>>}
> >>> }
> >>>
> >>> constructors.d(34): Error: constructor constructors.A.this (int x) is
> >>> not callable using argument types ()
> >>>
> >> 
> >> This is my new once-a-day bug :(
> >> Using a function alias, and being unable to call properties on it,
> >> because DMD thinks I'm calling it. Man, it's no property, just a name!
> >> 
> >> Anyway, just pragma(msg, m) works, strangely.
> >> I think I found a way to use m, somewhat:
> >> 
> >> void main() {
> >>foreach (m; __traits(getOverloads, A, "__ctor")) {
> >>pragma(msg, m); // it thinks I'm calling m
> >>typeof(&m) tmp = &m;
> >> writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double),
> >> (string)
> >> writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int)
> >> writeln( typeof(&m).stringof); // A function(int x), A
> >> function(double x), A function(string s)
> >>}
> >> }
> >> 
> >> using ParameterTypeTuple!m directly does not differentiate the m's. But
> >> using a temporary pointer, it seems to work.
> >> 
> >> Oh and I even get the arguments names !
> >> 
> >> 
> >> Philippe
> > 
> > Thanks!! works now. Now we just need to be able to select which
> > constructors we actually want.
> > 
> > string inheritconstructors_helper(alias T)() {
> > string s;
> > foreach (m; __traits(getOverloads, T, "__ctor")) {
> > string args, args1;
> > foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
> > pragma(msg, cons.stringof);
> > args ~= ","~cons.stringof~" v"~to!string(i);
> > args1 ~= ",v"~to!string(i);
> > }
> > args = args.length < 1 ? args : args[1..$];
> > args1 = args1.length < 1 ? args1 : args1[1..$];
> > s ~= "this("~args~") { super("~args1~"); }\n";
> > }
> > return s;
> > }
> > 
> > class A {
> > int i;
> > //private this() {}
> > this(int x) {
> > i = x;
> > }
> > this(float x) {
> > i = cast(int)x; // ignore bad code
> > }
> > this(string s, int mul) { // test multiple args
> > i = to!int(s) * mul;
> > }
> > }
> > class B : A {
> > mixin(inheritconstructors_helper!A());
> > //  InheritConstructors!A;
> > }
> > 
> > 
> > 
> > void main() {
> > A a = new B(4);
> > a = new B("42", 2);
> > }
> 
> Got selection working:
> 
> string inheritconstructors_helper(alias T,Selectors...)() {
> string s;
> 
> foreach (m; __traits(getOverloads, T, "__ctor")) {
> string args, args1;
> pragma(msg, typeof(&m));
> /*foreach (sel; Selectors) {
> pragma(msg, sel, is (sel == typeof(&m)));
> continue top;
> }*/
> if (staticIndexOf!(typeof(&m), Selectors)==-1) {
> continue;
> }
> foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
> pragma(msg, cons.stringof);
> args ~= ","~cons.stringof~" v"~to!string(i);
> args1 ~= ",v"~to!string(i);
> }
> args = args.length < 1 ? args : args[1..$];
> args1 = args1.length < 1 ? args1 : args1[1..$];
> s ~= "this("~args~") { super("~args1~"); }\n";
> }
> return s;
> }
> 
> 
> 
> Usage:
> 
> class B : A {
> mixin(inheritconstructors_helper!(A,TypeTuple!(A functi

Re: Operator overloading problem

2010-08-06 Thread div0

On 06/08/2010 22:24, Blonder wrote:

Hello,

this seems to work, but if I add the following

double opBinary(string op, U) (U rhs)
{
static if(op == "^"&&  is(U: Group))
{
// do something
return 42;
}
}

because I want to write the following: double d = g^h;
I have the same problem again.


You should only use the static if on the 2nd template parameter.
You want:

class Group {
voidopBinrary(string op, U)(U rhs)
if(op == "^") {
}

voidopBinrary(string op, U)(U rhs)
if(op == "+") {
}

voidopBinrary(string op, U)(U rhs)
if(op == "-") {
}

voidopBinrary(string op, U)(U rhs)
if(op == "*") {
}
}

Note that the 'if' is a template constraint is and part of the template 
signature; this is what stops you getting multiple matches when trying 
to determine which template to use.


You can only use the static if inside the function if all the types U 
are similar, otherwise you'll get conversion problems with return values 
and such.


>
> This syntax isn't very intuitive.
>

No programming language is intuitive; they all take time to learn.
D is a big win over C++ though and well worth sticking with.

--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Re: Operator overloading problem

2010-08-06 Thread Blonder
Hello,

this seems to work, but if I add the following

double opBinary(string op, U) (U rhs)
{
static if(op == "^" && is(U: Group))
{
// do something
return 42;
}
}

because I want to write the following: double d = g^h;
I have the same problem again.

This syntax isn't very intuitive.


Re: Operator overloading problem

2010-08-06 Thread Philippe Sigaud
On Fri, Aug 6, 2010 at 22:37, div0  wrote:

> Personally, I'm with you and I would expect that the compiler should
> example the function parameters after the template string parameter but it
> doesn't.
>

Yes :o(
You need to add a second template parameter for the function arguments and
add a template constrait like so:


> struct Group {
>int i1;
>
>Group opBinary(string op, U) (U x)
>if(op == "+" && is(U: int))
>{
>// do somehting
>return this;
>}
>
>Group opBinary(string op, U) (U rhs)
>if(op == "+" && is(U: Group))
>{
>// do something
>return this;
>}
> }
>
>
In some cases, you might factor things a bit:

Group opBinary(string op, U)(U u) if (op == "+")
{
   common code for all U's;

static if (some test on U)
  some code;
   else
 other code;
}

Maybe  some code is common between the Group case and the int case. I'm not
sure it's more readable this way...

Philippe


Re: inheriting ctors?

2010-08-06 Thread Philippe Sigaud
On Fri, Aug 6, 2010 at 21:59, Rory Mcguire  wrote:

>
> Here is a possible solution to your problem:
>
> -Rory


I believe you can get the type of A. Isn't it typeof(super) or
std.traits.BaseClassesTuple!B[0] ? B in the latter case being typeof(this)
That way, there is no need for the user to provide A, it's automatically
found by the template.
Warning: I did not test this.

And, we know the constructs are of type 'A function(someTypes)'  [*], so the
'A function' part is redundant.
Hence, the user only needs to provide for the args types and that makes for
a cleaner call.

* either as a list :
mixin(InheritConstructors!(int, double, string)); // I want to inherit
the constructors taking one type, build me the __ctors for int, double and
string

* or, in the case of multi-parameters constructors, wrap them in a tuple:
mixin(InheritConstructors!(int, double, Tuple!(int, double)); // I want
super(int), super(double) and super(int, double)

That means iterating on the type list, and determining if the current type
is a tuple or not
* if its a 'normal' type, create the corresponding contructor
* if it's a Tuple, crack it open and get the types, using the .Types alias
std.typecons.Tuples have. Creating a constructor from this typetuple is no
different from creating it for one type.

To determine if something is a std.typecons.Tuple, you cannot use an is()
expression: they do not allow multiple types:

enum bool isTuple = is(T == Tuple!U, U...); // no. U... is not allowed. Hmm,
enhancement request?

So, you can either rely on it having a .Types 'member':

template isTuple(T)
{
  enum bool isTuple = is(T.Types);
}

Pb: that will flag as tuples any type that exposes a ".Types" alias.

Or use a function accepting a Tuple:

template isTuple(T)
{
enum bool isTuple = is(typeof({
   void foo(U...)(Tuple!U t) {}; // this
function accepts only tuples
   foo(T.init); // test it
  }()));
}

It's ugly as a rat's ass, but it's more solid than the former template.


Philippe

[*] btw, shouldn't that be A delegate(someTypes)???


Re: Operator overloading problem

2010-08-06 Thread div0

On 06/08/2010 21:37, div0 wrote:



You need to add a second template parameter for the function arguments
and add a template constrait like so:

struct Group {
int i1;

Group opBinary(string op, U) (U x)
if(op == "+" && is(U: int))
{
// do somehting
return this;
}

Group opBinary(string op, U) (U rhs)
if(op == "+" && is(U: Group))
{
// do something
return this;
}
}


And if you are old school C++ and don't like these new fangled template 
constraints you can use specialisation as well:


struct Group {
int i1;

Group opBinary(string op : "+", U: int) (U x) {
// do somehting
return this;
}

Group opBinary(string op : "+", U: Group) (U rhs) {
// do something
return this;
}
}


--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Re: Operator overloading problem

2010-08-06 Thread div0

On 06/08/2010 21:08, Blonder wrote:

Hello, I am trying to understand how operator overloading works with D. I am a 
C++
programmer and I am reading the book of Andrei Alexandrescu and try to 
understand
D and it's language features.

My Group example don't compile, the error is:
Error: template instance opBinary!("+") matches more than one template
declaration, ...

I know that it matches more than one, that was my intention, because I want to 
be
able to write also

h = g+2 for example.

Is this possible in D?
Can you help me?
Thanks,
Andreas.



You need to add a second template parameter for the function arguments 
and add a template constrait like so:


struct Group {
int i1;

Group opBinary(string op, U) (U x)
if(op == "+" && is(U: int))
{
// do somehting
return this;
}

Group opBinary(string op, U) (U rhs)
if(op == "+" && is(U: Group))
{
// do something
return this;
}
}


void main() {
Group g, h;
g.i1 = 1;

h = g+g;
}

Personally, I'm with you and I would expect that the compiler should 
example the function parameters after the template string parameter but 
it doesn't.


It's important to note: you must use the template parameter U, you can 
not explitictly use the type (int/Group) like you can in C++.


ie you can't do:

struct Group {
int i1;

// DOES NOT WORK
Group opBinary(string op, U) (int x)
if(op == "+" && is(U: int))
{
// do somehting
return this;
}

// DOES NOT WORK
Group opBinary(string op, U) (Group rhs)
if(op == "+" && is(U: Group))
{
// do something
return this;
}
}

--
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk


Re: Operator overloading problem

2010-08-06 Thread Blonder
Hello, I am trying to understand how operator overloading works with D. I am a 
C++
programmer and I am reading the book of Andrei Alexandrescu and try to 
understand
D and it's language features.

My Group example don't compile, the error is:
Error: template instance opBinary!("+") matches more than one template
declaration, ...

I know that it matches more than one, that was my intention, because I want to 
be
able to write also

h = g+2 for example.

Is this possible in D?
Can you help me?
Thanks,
Andreas.



Re: inheriting ctors?

2010-08-06 Thread Rory Mcguire
dcoder wrote:

> Suppose I have a base class with many ctors().
> 
> I want to inherit from the base class and make one slight alteration to
> it, but I don't want to write X times the following:
> 
> this(args) {
>   super(args);
> }
> 
> Does D have an easy way for the derived class to 'inherit' all or some of
> the base class ctors(), and just override/add ctors() in the derived
> class?
> 
> In Java, we can use eclipse to auto-generate code for us.  :)  But,
> the results look cluttered, and it's really not a solution.
> 
> Anyways, just curious.
> 
> thanks.

Here is a possible solution to your problem:

-Roryimport std.traits, std.conv, std.typetuple;
/** Generates constructors for a super class in one of its sub classes
 *  mixin(inheritconstructors_helper!(class, types of constructors to export)();
 */
string inheritconstructors_helper(alias T,Selectors...)() if (is (T == class)) {
	string s="";
	foreach (m; __traits(getOverloads, T, "__ctor")) {
		string args, args1;
		if (Selectors.length > 0 && staticIndexOf!(typeof(&m), Selectors)==-1) { // don't export constructors that aren't requested
			continue;
		}
		foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
			args ~= ","~cons.stringof~" v"~to!string(i); // declaration arguments
			args1 ~= ",v"~to!string(i);	// arguments for super(???) call
		}
		args = args.length < 1 ? args : args[1..$];
		args1 = args1.length < 1 ? args1 : args1[1..$];
		s ~= "this("~args~") { super("~args1~"); }\n";
	}
	return s;
}

class A {
	double myd;
	this(int x) { myd = x; }
	this(float x) { myd = x; }
	this(string s, int mul) { myd = to!double(s)*mul; }
}
class B : A {
//	mixin(inheritconstructors_helper!(A,TypeTuple!(A function(string,int),A function(int)))()); // only import the two specified constructors
//	mixin(inheritconstructors_helper!(A,void)()); // ends up as empty string
	mixin(inheritconstructors_helper!(A)()); // import all constructors from parent class
}


void main() {
	A a = new B(4);
	a = new B("42",2);
}



Re: Operator overloading problem

2010-08-06 Thread Jonathan M Davis
On Friday, August 06, 2010 12:30:38 Blonder wrote:
> Hello,
> 
> can someone help me with this?
> 
> struct Group {
> int i1;
> Group opBinary(string op)(int x) {
> // do somehting
> return this;
> }
> Group opBinary(string op)(Group g) {
> // do something
> return this;
> }
> }
> 
> 
> Group g, h;
> g.i1 = 1;
> 
> h = g+g;

I think that you need to be more specific with your question. What exactly do 
you 
want help with? Are you trying to figure out how operator overloading works? 
Are 
you trying to figure out how it would be specifically done in this case? What 
exactly are you looking for help with?

- Jonathan M Davis


Operator overloading problem

2010-08-06 Thread Blonder
Hello,

can someone help me with this?

struct Group {
int i1;
Group opBinary(string op)(int x) {
// do somehting
return this;
}
Group opBinary(string op)(Group g) {
// do something
return this;
}
}


Group g, h;
g.i1 = 1;

h = g+g;


Re: inheriting ctors?

2010-08-06 Thread Rory Mcguire
Rory Mcguire wrote:

> Philippe Sigaud wrote:
> 
>> On Fri, Aug 6, 2010 at 11:43, Rory Mcguire 
>> wrote:
>> 
>> 
>>> I've been trying to make a template for this but it seems that dmd still
>>> won't allow me to get the parameters of the constructors. dmd Seems to
>>> think
>>> that I'm trying to use it as a property.
>>>
>>>
>> 
>>> void main() {
>>>foreach (m; __traits(getOverloads, A, "__ctor")) {
>>>pragma(msg, m.stringof); // it thinks I'm calling m
>>>}
>>> }
>>>
>>> constructors.d(34): Error: constructor constructors.A.this (int x) is
>>> not callable using argument types ()
>>>
>> 
>> This is my new once-a-day bug :(
>> Using a function alias, and being unable to call properties on it,
>> because DMD thinks I'm calling it. Man, it's no property, just a name!
>> 
>> Anyway, just pragma(msg, m) works, strangely.
>> I think I found a way to use m, somewhat:
>> 
>> void main() {
>>foreach (m; __traits(getOverloads, A, "__ctor")) {
>>pragma(msg, m); // it thinks I'm calling m
>>typeof(&m) tmp = &m;
>> writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double),
>> (string)
>> writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int)
>> writeln( typeof(&m).stringof); // A function(int x), A
>> function(double x), A function(string s)
>>}
>> }
>> 
>> using ParameterTypeTuple!m directly does not differentiate the m's. But
>> using a temporary pointer, it seems to work.
>> 
>> Oh and I even get the arguments names !
>> 
>> 
>> Philippe
> 
> Thanks!! works now. Now we just need to be able to select which
> constructors we actually want.
> 
> string inheritconstructors_helper(alias T)() {
> string s;
> foreach (m; __traits(getOverloads, T, "__ctor")) {
> string args, args1;
> foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
> pragma(msg, cons.stringof);
> args ~= ","~cons.stringof~" v"~to!string(i);
> args1 ~= ",v"~to!string(i);
> }
> args = args.length < 1 ? args : args[1..$];
> args1 = args1.length < 1 ? args1 : args1[1..$];
> s ~= "this("~args~") { super("~args1~"); }\n";
> }
> return s;
> }
> 
> class A {
> int i;
> //private this() {}
> this(int x) {
> i = x;
> }
> this(float x) {
> i = cast(int)x; // ignore bad code
> }
> this(string s, int mul) { // test multiple args
> i = to!int(s) * mul;
> }
> }
> class B : A {
> mixin(inheritconstructors_helper!A());
> //  InheritConstructors!A;
> }
> 
> 
> 
> void main() {
> A a = new B(4);
> a = new B("42", 2);
> }

Got selection working:

string inheritconstructors_helper(alias T,Selectors...)() {
string s;

foreach (m; __traits(getOverloads, T, "__ctor")) {
string args, args1;
pragma(msg, typeof(&m));
/*foreach (sel; Selectors) {
pragma(msg, sel, is (sel == typeof(&m)));
continue top;
}*/
if (staticIndexOf!(typeof(&m), Selectors)==-1) {
continue;
}
foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
pragma(msg, cons.stringof);
args ~= ","~cons.stringof~" v"~to!string(i);
args1 ~= ",v"~to!string(i);
}
args = args.length < 1 ? args : args[1..$];
args1 = args1.length < 1 ? args1 : args1[1..$];
s ~= "this("~args~") { super("~args1~"); }\n";
}
return s;
}



Usage:

class B : A {
mixin(inheritconstructors_helper!(A,TypeTuple!(A function(string,int)
,A function(int)))());
}



Re: ref is pointer sugar?

2010-08-06 Thread Pluto
== Quote from Jacob Carlborg (d...@me.com)'s article
> On 2010-08-06 15:33, Pluto wrote:
> > == Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article
> >> On Fri, 06 Aug 2010 08:51:31 -0400, Pluto  wrote:
> >>> Are these equivalent?
> >>>
> >>> S s;//struct
> >>>
> >>> void f(ref S s){s.x++;}
> >>> f(s);
> >>>
> >>> void f2(S* s){(*s).x++;}
> >>> f2(&s);
> >> They are pretty much equivalent.  I think the code generated actually will
> >> be exactly the same.  However, the compiler treats ref differently than
> >> pointers.  For example, ref is allowed in the safe subset of D, and
> >> pointers are not.
> >> Note that you do not need to dereference pointers to access their
> >> pointed-to members.  i.e.:
> >> void f2(S* s){s.x++;}
> >
> > Where is this in the spec? I can't find it. Still used to ->
> http://www.digitalmars.com/d/1.0/class.html section "Fields".
And this is more generally also applicable to dereferencing pointers.
Isn't that showing a bit of a gap in the specs? (bug report?)


Re: inheriting ctors?

2010-08-06 Thread Rory Mcguire
Philippe Sigaud wrote:

> On Fri, Aug 6, 2010 at 11:43, Rory Mcguire 
> wrote:
> 
> 
>> I've been trying to make a template for this but it seems that dmd still
>> won't allow me to get the parameters of the constructors. dmd Seems to
>> think
>> that I'm trying to use it as a property.
>>
>>
> 
>> void main() {
>>foreach (m; __traits(getOverloads, A, "__ctor")) {
>>pragma(msg, m.stringof); // it thinks I'm calling m
>>}
>> }
>>
>> constructors.d(34): Error: constructor constructors.A.this (int x) is not
>> callable using argument types ()
>>
> 
> This is my new once-a-day bug :(
> Using a function alias, and being unable to call properties on it, because
> DMD thinks I'm calling it. Man, it's no property, just a name!
> 
> Anyway, just pragma(msg, m) works, strangely.
> I think I found a way to use m, somewhat:
> 
> void main() {
>foreach (m; __traits(getOverloads, A, "__ctor")) {
>pragma(msg, m); // it thinks I'm calling m
>typeof(&m) tmp = &m;
> writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double),
> (string)
> writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int)
> writeln( typeof(&m).stringof); // A function(int x), A
> function(double x), A function(string s)
>}
> }
> 
> using ParameterTypeTuple!m directly does not differentiate the m's. But
> using a temporary pointer, it seems to work.
> 
> Oh and I even get the arguments names !
> 
> 
> Philippe

Thanks!! works now. Now we just need to be able to select which constructors 
we actually want.

string inheritconstructors_helper(alias T)() {
string s;
foreach (m; __traits(getOverloads, T, "__ctor")) {
string args, args1;
foreach (i, cons; ParameterTypeTuple!(typeof(&m))) {
pragma(msg, cons.stringof);
args ~= ","~cons.stringof~" v"~to!string(i);
args1 ~= ",v"~to!string(i);
}
args = args.length < 1 ? args : args[1..$];
args1 = args1.length < 1 ? args1 : args1[1..$];
s ~= "this("~args~") { super("~args1~"); }\n";
}
return s;
}

class A {
int i;
//private this() {}
this(int x) {
i = x;
}
this(float x) {
i = cast(int)x; // ignore bad code
}
this(string s, int mul) { // test multiple args
i = to!int(s) * mul;
}
}
class B : A {
mixin(inheritconstructors_helper!A());
//  InheritConstructors!A;
}



void main() {
A a = new B(4);
a = new B("42", 2);
}







Re: inheriting ctors?

2010-08-06 Thread Philippe Sigaud
On Fri, Aug 6, 2010 at 19:09, bearophile  wrote:

> Philippe Sigaud:
> > This is my new once-a-day bug :(
>
> Add them all to Bugzilla :-)
>

I do, from time to time. But I'm never sure if it's a bug or not.

It's related to The Great And Neverending Property Debate (tm). So I don't
what to believe.


Philippe


Re: inheriting ctors?

2010-08-06 Thread bearophile
Philippe Sigaud:
> This is my new once-a-day bug :(

Add them all to Bugzilla :-)

Bye,
bearophile


Re: inheriting ctors?

2010-08-06 Thread Philippe Sigaud
On Fri, Aug 6, 2010 at 11:43, Rory Mcguire  wrote:


> I've been trying to make a template for this but it seems that dmd still
> won't allow me to get the parameters of the constructors. dmd Seems to
> think
> that I'm trying to use it as a property.
>
>

> void main() {
>foreach (m; __traits(getOverloads, A, "__ctor")) {
>pragma(msg, m.stringof); // it thinks I'm calling m
>}
> }
>
> constructors.d(34): Error: constructor constructors.A.this (int x) is not
> callable using argument types ()
>

This is my new once-a-day bug :(
Using a function alias, and being unable to call properties on it, because
DMD thinks I'm calling it. Man, it's no property, just a name!

Anyway, just pragma(msg, m) works, strangely.
I think I found a way to use m, somewhat:

void main() {
   foreach (m; __traits(getOverloads, A, "__ctor")) {
   pragma(msg, m); // it thinks I'm calling m
   typeof(&m) tmp = &m;
writeln( (ParameterTypeTuple!tmp).stringof); // (int), (double),
(string)
writeln( (ParameterTypeTuple!m).stringof); // (int), (int), (int)
writeln( typeof(&m).stringof); // A function(int x), A
function(double x), A function(string s)
   }
}

using ParameterTypeTuple!m directly does not differentiate the m's. But
using a temporary pointer, it seems to work.

Oh and I even get the arguments names !


Philippe


Re: ref is pointer sugar?

2010-08-06 Thread Jacob Carlborg

On 2010-08-06 15:33, Pluto wrote:

== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article

On Fri, 06 Aug 2010 08:51:31 -0400, Pluto  wrote:

Are these equivalent?

S s;//struct

void f(ref S s){s.x++;}
f(s);

void f2(S* s){(*s).x++;}
f2(&s);

They are pretty much equivalent.  I think the code generated actually will
be exactly the same.  However, the compiler treats ref differently than
pointers.  For example, ref is allowed in the safe subset of D, and
pointers are not.
Note that you do not need to dereference pointers to access their
pointed-to members.  i.e.:
void f2(S* s){s.x++;}


Where is this in the spec? I can't find it. Still used to ->


http://www.digitalmars.com/d/1.0/class.html section "Fields".

--
/Jacob Carlborg


Re: Do I have to cast double to cdouble everywhere?

2010-08-06 Thread bearophile
John Travers:
> c1 = cast(cdouble)2.0;

Casts are bad, better to avoid them when possible.
You can do this:

void main() {
  cdouble c1;
  c1 = 2.0 + 0i;
}

But complex numbers will be removed from D, they will become partially library 
ones (imaginary ones will probably just removed). I think they will hopefully 
keep the same good enough syntax.

Bye,
bearophile


Re: ref is pointer sugar?

2010-08-06 Thread Pluto
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article
> On Fri, 06 Aug 2010 08:51:31 -0400, Pluto  wrote:
> > Are these equivalent?
> >
> > S s;//struct
> >
> > void f(ref S s){s.x++;}
> > f(s);
> >
> > void f2(S* s){(*s).x++;}
> > f2(&s);
> They are pretty much equivalent.  I think the code generated actually will
> be exactly the same.  However, the compiler treats ref differently than
> pointers.  For example, ref is allowed in the safe subset of D, and
> pointers are not.
> Note that you do not need to dereference pointers to access their
> pointed-to members.  i.e.:
> void f2(S* s){s.x++;}

Where is this in the spec? I can't find it. Still used to ->


Do I have to cast double to cdouble everywhere?

2010-08-06 Thread John Travers
Hi,

I'm investigating if D would be useful to me as a numerical programming
language to replace my current mix of fortran and python.

I'm stuck with a problem which seems odd to me:

cdouble c1;
c1 = 2.0;

complains:

Error: cannot implicitly convert expression (2) of type double to cdouble

The only way I can find to solve this is by doing:

c1 = cast(cdouble)2.0;

This will drive me crazy, many numeric codes need to multiply complex numbers,
or assign to them, with real numbers. This problem also occurs with imaginary
numbers.

Is there a simple solution to this without covering all my code with casts?

Thanks for any help!

Regards,
John



Re: ref is pointer sugar?

2010-08-06 Thread Pluto
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article
> On Fri, 06 Aug 2010 08:51:31 -0400, Pluto  wrote:
> > Are these equivalent?
> >
> > S s;//struct
> >
> > void f(ref S s){s.x++;}
> > f(s);
> >
> > void f2(S* s){(*s).x++;}
> > f2(&s);
> They are pretty much equivalent.  I think the code generated actually will
> be exactly the same.  However, the compiler treats ref differently than
> pointers.  For example, ref is allowed in the safe subset of D, and
> pointers are not.
> Note that you do not need to dereference pointers to access their
> pointed-to members.  i.e.:
> void f2(S* s){s.x++;}
> >
> > If so, why is it stated that ref is very rarely used?
> > It looks like something I would use a lot with structures.
> What?  Where does it say that?  That's very wrong, ref is used
> everywhere.  If not explicitly, at least every struct member function
> passes 'this' by ref.
> -Steve
I read it on the function page of D1.
"out is rare enough, and ref even rarer, to attach the keywords to them and 
leave
in as the default. "
I would think out to be more rare then ref.


Re: ref is pointer sugar?

2010-08-06 Thread Steven Schveighoffer

On Fri, 06 Aug 2010 08:51:31 -0400, Pluto  wrote:


Are these equivalent?

S s;//struct

void f(ref S s){s.x++;}
f(s);

void f2(S* s){(*s).x++;}
f2(&s);


They are pretty much equivalent.  I think the code generated actually will  
be exactly the same.  However, the compiler treats ref differently than  
pointers.  For example, ref is allowed in the safe subset of D, and  
pointers are not.


Note that you do not need to dereference pointers to access their  
pointed-to members.  i.e.:


void f2(S* s){s.x++;}



If so, why is it stated that ref is very rarely used?
It looks like something I would use a lot with structures.


What?  Where does it say that?  That's very wrong, ref is used  
everywhere.  If not explicitly, at least every struct member function  
passes 'this' by ref.


-Steve


ref is pointer sugar?

2010-08-06 Thread Pluto
Are these equivalent?

S s;//struct

void f(ref S s){s.x++;}
f(s);

void f2(S* s){(*s).x++;}
f2(&s);

If so, why is it stated that ref is very rarely used?
It looks like something I would use a lot with structures.


Re: Isn't __traits part of the language?

2010-08-06 Thread Steven Schveighoffer
On Fri, 06 Aug 2010 08:42:40 -0400, simendsjo   
wrote:



Rationale (http://digitalmars.com/d/2.0/rationale.html) says:
"""Why not use operator names like __add__ and __div__ instead of opAdd,  
opDiv, etc.?


__ keywords should indicate a proprietary language extension, not a  
basic part of the language. """



But traits is explained under the language spec,  
http://digitalmars.com/d/2.0/traits.html.



Can I expect traits to exist for all compiler implementations, or just  
dmd?


__traits was an experiment, one that is highly successful, and will likely  
be a permanent part of the language.


It has been suggested that we choose a keyword to replace __traits, meta  
was one such suggestion that I like.  AFAIK, Walter hasn't really  
commented on it.


-Steve


Isn't __traits part of the language?

2010-08-06 Thread simendsjo

Rationale (http://digitalmars.com/d/2.0/rationale.html) says:
"""Why not use operator names like __add__ and __div__ instead of opAdd, 
opDiv, etc.?


__ keywords should indicate a proprietary language extension, not a 
basic part of the language. """



But traits is explained under the language spec, 
http://digitalmars.com/d/2.0/traits.html.



Can I expect traits to exist for all compiler implementations, or just dmd?


Re: inheriting ctors?

2010-08-06 Thread Rory Mcguire
Sean Kelly wrote:

> Steven Schveighoffer Wrote:
> 
>> On Thu, 05 Aug 2010 13:53:20 -0400, dcoder  wrote:
>> 
>> > Suppose I have a base class with many ctors().
>> >
>> > I want to inherit from the base class and make one slight alteration to
>> > it,
>> > but I don't want to write X times the following:
>> >
>> > this(args) {
>> >   super(args);
>> > }
>> >
>> > Does D have an easy way for the derived class to 'inherit' all or some
>> > of the
>> > base class ctors(), and just override/add ctors() in the derived class?
>> 
>> Sadly, no.  It's been discussed in the past.  I was surprised there were
>> no enhancement requests for it in bugzilla, care to add one?
> 
> If it helps, I wrote up something on this a few years back:
> 
> 
http://www.digitalmars.com/d/archives/digitalmars/D/Inheriting_constructors_54088.html
> 
> Might be a good starting point for an enhancement request.


I've been trying to make a template for this but it seems that dmd still 
won't allow me to get the parameters of the constructors. dmd Seems to think 
that I'm trying to use it as a property.

Using getOverloads, one should be able to generate or select any of super's 
constructors. No need for enhancement, just a bug fix. see below:

import std.traits;
import std.conv;


class A {
int i;
this(int x) {
i = x;
}
this(float x) {
i = cast(int)x; // ignore bad code
}
this(string s) {
i = to!int(s);
}
}
void main() {
foreach (m; __traits(getOverloads, A, "__ctor")) {
pragma(msg, m.stringof); // it thinks I'm calling m
}
}

constructors.d(34): Error: constructor constructors.A.this (int x) is not 
callable using argument types ()
constructors.d(34): Error: expected 1 function arguments, not 0
this()
constructors.d(34): Error: constructor constructors.A.this (float x) is not 
callable using argument types ()
constructors.d(34): Error: expected 1 function arguments, not 0
this()
constructors.d(34): Error: constructor constructors.A.this (string s) is not 
callable using argument types ()
constructors.d(34): Error: expected 1 function arguments, not 0
this()