www.digitalmars.com         C & C++   DMDScript  

D - DMD compiler does like template recursion

reply Roel Mathys <roel.mathys yucom.be> writes:
that is version .79 does

bye,
roel
-----------------------

template factor(int i)
{
	const int value = i * factor!(i-1).value;
}

template factor(int i : 0)
{
	const int value = 1;
}

int main()
{
	int f = factor!(5).value;
	printf("%d\n",f);
	
	return 0;
}
Jan 22 2004
next sibling parent Georg Wrede <Georg_member pathlink.com> writes:
In article <bup7bl$2t43$1 digitaldaemon.com>, Roel Mathys says...
that is version .79 does

bye,
roel
-----------------------

template factor(int i)
{
	const int value = i * factor!(i-1).value;
}

template factor(int i : 0)
{
	const int value = 1;
}

int main()
{
	int f = factor!(5).value;
	printf("%d\n",f);
	
	return 0;
}

Somebody better explain this to me! I would've thought that functions are chose by signature, and not by value??
Jan 22 2004
prev sibling next sibling parent reply "C" <dont respond.com> writes:
Can someone explain to me the benefits of this ( meta programming ? )
besides finding 5 factorial ?  The only artical I read on it using C++ did
the same thing , what other uses does it have ?

Thanks,
C
"Roel Mathys" <roel.mathys yucom.be> wrote in message
news:bup7bl$2t43$1 digitaldaemon.com...
 that is version .79 does

 bye,
 roel
 -----------------------

 template factor(int i)
 {
 const int value = i * factor!(i-1).value;
 }

 template factor(int i : 0)
 {
 const int value = 1;
 }

 int main()
 {
 int f = factor!(5).value;
 printf("%d\n",f);

 return 0;
 }

Jan 22 2004
next sibling parent "Robert" <no spam.ne.jp> writes:
That realizes:

    const int Size = factor!(5).value;
    int[Size] n;


"C" <dont respond.com> wrote in message
news:bupp7r$pa3$1 digitaldaemon.com...
 Can someone explain to me the benefits of this ( meta programming ? )
 besides finding 5 factorial ?  The only artical I read on it using C++ did
 the same thing , what other uses does it have ?

 Thanks,
 C
 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:bup7bl$2t43$1 digitaldaemon.com...
 that is version .79 does

 bye,
 roel
 -----------------------

 template factor(int i)
 {
 const int value = i * factor!(i-1).value;
 }

 template factor(int i : 0)
 {
 const int value = 1;
 }

 int main()
 {
 int f = factor!(5).value;
 printf("%d\n",f);

 return 0;
 }


Jan 22 2004
prev sibling next sibling parent Andy Friesen <andy ikagames.com> writes:
C wrote:

 Can someone explain to me the benefits of this ( meta programming ? )
 besides finding 5 factorial ?  The only artical I read on it using C++ did
 the same thing , what other uses does it have ?

I've heard of it being used to get the compiler to generate lookup tables. It also has uses in places where you want to loop some number of times that is known at compile time, but don't want the runtime overhead of a loop. (matrix multiplication, for instance, can be done with template metaprogramming, if the matrix dimensions are template arguments) This is definitely one of the cooler things about C++ templates, but, come to think of it, it's not useful in a whole lot of cases. Regardless, it's neat to know that D can swallow it. :) -- andy
Jan 22 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
A question with an enormous answer.

I can't think of a smart answer right now, but I can assure you that DTL
will make intelligent use of meta programming techniques. Promise. :)

"C" <dont respond.com> wrote in message
news:bupp7r$pa3$1 digitaldaemon.com...
 Can someone explain to me the benefits of this ( meta programming ? )
 besides finding 5 factorial ?  The only artical I read on it using C++ did
 the same thing , what other uses does it have ?

 Thanks,
 C
 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:bup7bl$2t43$1 digitaldaemon.com...
 that is version .79 does

 bye,
 roel
 -----------------------

 template factor(int i)
 {
 const int value = i * factor!(i-1).value;
 }

 template factor(int i : 0)
 {
 const int value = 1;
 }

 int main()
 {
 int f = factor!(5).value;
 printf("%d\n",f);

 return 0;
 }


Jan 22 2004
parent reply "Matthias Spycher" <matthias coware.com> writes:
Modern C++ Design: Generic Programming and Design Patterns Applied
by Andrei Alexandrescu (Author)

C++ Templates: The Complete Guide
by David Vandevoorde (Author), Nicolai M. Josuttis (Author)

The two books explain in depth what's possible in C++ and how painful it is
to implement when you take into consideration requirements like argument
dependent lookup (ADL). Many of the techniques described probably apply to D
templates as well.

I have been working on a C++ source-to-source transformation engine for a
global optimizer that is aware of special library semantics. We use EDG
(written in part by the first author of the second book mentioned above) as
a front-end for parsing and semantic analysis. Depending on how you look at
it, this code base is both beautiful and ugly at the same time. You marvel
at the beauty because of what it accomplishes and yet you dread its
maintenance because the complexity inherent in C++ renders it terribly
fragile.

Cheers
Matthias

"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:buptji$10ej$1 digitaldaemon.com...
 A question with an enormous answer.

 I can't think of a smart answer right now, but I can assure you that DTL
 will make intelligent use of meta programming techniques. Promise. :)

 "C" <dont respond.com> wrote in message
 news:bupp7r$pa3$1 digitaldaemon.com...
 Can someone explain to me the benefits of this ( meta programming ? )
 besides finding 5 factorial ?  The only artical I read on it using C++


 the same thing , what other uses does it have ?

 Thanks,
 C
 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:bup7bl$2t43$1 digitaldaemon.com...
 that is version .79 does

 bye,
 roel
 -----------------------

 template factor(int i)
 {
 const int value = i * factor!(i-1).value;
 }

 template factor(int i : 0)
 {
 const int value = 1;
 }

 int main()
 {
 int f = factor!(5).value;
 printf("%d\n",f);

 return 0;
 }



Jan 22 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Matthias Spycher" <matthias coware.com> wrote in message
news:buqdjo$1r0j$1 digitaldaemon.com...
 Modern C++ Design: Generic Programming and Design Patterns Applied
 by Andrei Alexandrescu (Author)

 C++ Templates: The Complete Guide
 by David Vandevoorde (Author), Nicolai M. Josuttis (Author)

 The two books explain in depth what's possible in C++ and how painful it

 to implement when you take into consideration requirements like argument
 dependent lookup (ADL). Many of the techniques described probably apply to

 templates as well.

 I have been working on a C++ source-to-source transformation engine for a
 global optimizer that is aware of special library semantics. We use EDG
 (written in part by the first author of the second book mentioned above)

 a front-end for parsing and semantic analysis. Depending on how you look

 it, this code base is both beautiful and ugly at the same time. You marvel
 at the beauty because of what it accomplishes and yet you dread its
 maintenance because the complexity inherent in C++ renders it terribly
 fragile.

Since you're very familiar with this, I'd be interested in your take on whether D's template syntax and semantics improves on it or not, and why. (I have the 2nd book, but not the first.) D templates *will* go under the microscope by the C++ template experts sooner or later, and I'd rather get the critiques of it sooner!
Jan 22 2004
next sibling parent reply Roel Mathys <roel.mathys yucom.be> writes:
The code here under (slightly adapted from C++ to D off course) does not 
generate a virtual table in C++. These result compile-time dispatching. 
Is the D compiler capable of optimizing away the virtualness?

I don't think so because of the following extract.

 From the website:

	D differs from C/C++ in another aspect of casts. Any casting of
	a class reference to a derived class reference is done with a
	runtime check to make sure it really is a proper downcast. This
	means that it is equivalent to the behavior of the dynamic_cast
	operator in C++.

C++ has - beside dynamic_cast - a static_cast operator, which is used in 
this case.

Maybe there are other ways to do it in D, but I am not aware off them at 
this moment.

BTW, this is heavily and heavenly used in WTL, a GUI library for Win32.

bye,
roel

/+ ---------------------------------------------- +/
template H(T)
{
	class Base
	{
		void GetInfo()
		{
			T* t = cast(T*)(&this);
			t.Info();
		}
		void Info() { printf("This is a Base instance.\n"); }
	}
}

class D1 : H!(D1).Base
{
	// No overrides
}

class D2 : H!(D1).Base
{
	void Info() { printf("This is a D2 instance.\n"); }
}

int main()
{
	D1 d1 = new D1;
	D2 d2 = new D2;

	d1.GetInfo();
	d2.GetInfo();
	
	return 0;
}
Jan 23 2004
parent reply "Walter" <walter digitalmars.com> writes:
You can get the same effect as a C++ static_cast<Foo*>f with:
    cast(Foo)cast(void*)f;

"Roel Mathys" <roel.mathys yucom.be> wrote in message
news:burvng$1el1$1 digitaldaemon.com...
 The code here under (slightly adapted from C++ to D off course) does not
 generate a virtual table in C++. These result compile-time dispatching.
 Is the D compiler capable of optimizing away the virtualness?

 I don't think so because of the following extract.

  From the website:

 D differs from C/C++ in another aspect of casts. Any casting of
 a class reference to a derived class reference is done with a
 runtime check to make sure it really is a proper downcast. This
 means that it is equivalent to the behavior of the dynamic_cast
 operator in C++.

 C++ has - beside dynamic_cast - a static_cast operator, which is used in
 this case.

 Maybe there are other ways to do it in D, but I am not aware off them at
 this moment.

 BTW, this is heavily and heavenly used in WTL, a GUI library for Win32.

 bye,
 roel

 /+ ---------------------------------------------- +/
 template H(T)
 {
 class Base
 {
 void GetInfo()
 {
 T* t = cast(T*)(&this);
 t.Info();
 }
 void Info() { printf("This is a Base instance.\n"); }
 }
 }

 class D1 : H!(D1).Base
 {
 // No overrides
 }

 class D2 : H!(D1).Base
 {
 void Info() { printf("This is a D2 instance.\n"); }
 }

 int main()
 {
 D1 d1 = new D1;
 D2 d2 = new D2;

 d1.GetInfo();
 d2.GetInfo();

 return 0;
 }

Jan 23 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
 You can get the same effect as a C++ static_cast<Foo*>f with:
     cast(Foo)cast(void*)f;

Is the obscene unattractiveness of that deliberate? If so, bravo! If not, then can we have something easier on the eye?
 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:burvng$1el1$1 digitaldaemon.com...
 The code here under (slightly adapted from C++ to D off course) does not
 generate a virtual table in C++. These result compile-time dispatching.
 Is the D compiler capable of optimizing away the virtualness?

 I don't think so because of the following extract.

  From the website:

 D differs from C/C++ in another aspect of casts. Any casting of
 a class reference to a derived class reference is done with a
 runtime check to make sure it really is a proper downcast. This
 means that it is equivalent to the behavior of the dynamic_cast
 operator in C++.

 C++ has - beside dynamic_cast - a static_cast operator, which is used in
 this case.

 Maybe there are other ways to do it in D, but I am not aware off them at
 this moment.

 BTW, this is heavily and heavenly used in WTL, a GUI library for Win32.

 bye,
 roel

 /+ ---------------------------------------------- +/
 template H(T)
 {
 class Base
 {
 void GetInfo()
 {
 T* t = cast(T*)(&this);
 t.Info();
 }
 void Info() { printf("This is a Base instance.\n"); }
 }
 }

 class D1 : H!(D1).Base
 {
 // No overrides
 }

 class D2 : H!(D1).Base
 {
 void Info() { printf("This is a D2 instance.\n"); }
 }

 int main()
 {
 D1 d1 = new D1;
 D2 d2 = new D2;

 d1.GetInfo();
 d2.GetInfo();

 return 0;
 }


Jan 23 2004
parent "Walter" <walter digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:buseqr$26v7$1 digitaldaemon.com...
 You can get the same effect as a C++ static_cast<Foo*>f with:
     cast(Foo)cast(void*)f;

Is the obscene unattractiveness of that deliberate?

Trying to evade the type checking should look a bit less natural.
 If so, bravo! If not,
 then can we have something easier on the eye?

No <g>.
Jan 23 2004
prev sibling next sibling parent reply Roel Mathys <roel.mathys yucom.be> writes:
Walter,

a few points, I'll try to get back into the C++ templates, to try to 
search some more differences.
but upfront:

- for me is D's syntax better, nicer, not so heavy as in C++
- D has alias

- templatised functions
   => C++ : there is some type deduction going on,
            so one does not have to specify all the types

       e.g. template<typename T> f( T t ) { return 2*t; }
            can be invoked with
            f(5);
            instead of
            f<int>f(5);


bye,
roel
Jan 24 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Roel Mathys" <roel.mathys yucom.be> wrote in message
news:butkgu$13lk$1 digitaldaemon.com...
 Walter,

 a few points, I'll try to get back into the C++ templates, to try to
 search some more differences.
 but upfront:

 - for me is D's syntax better, nicer, not so heavy as in C++
 - D has alias

 - templatised functions
    => C++ : there is some type deduction going on,
             so one does not have to specify all the types

        e.g. template<typename T> f( T t ) { return 2*t; }
             can be invoked with
             f(5);
             instead of
             f<int>f(5);

Right, template argument deduction for function templates is something D templates don't do. I know how to do it (having implemented it for C++!), but I'm not sure it belongs in D.
Jan 24 2004
next sibling parent reply Roel Mathys <roel.mathys yucom.be> writes:
Walter wrote:

 Right, template argument deduction for function templates is something D
 templates don't do. I know how to do it (having implemented it for C++!),
 but I'm not sure it belongs in D.

in C++ templates code blocks (excuse me if this is not the correct term) are connected to a class or to a function (and other constructs). in D templates themselves form a code block, that's a big difference I think and might complicate type deduction. By being a code block itself, you can do a lot of the stuff in this block that in C++ is done with inner classes. e.g. for type deduction, it would be nice to have a template for the this constructor so that (any) value passed will be cast to a bit, whether it be class instance or a primitive instance. This naturally without the need to explicitly mention the type of the argument. class bool { bit value_ = false; this() {} this( bit b ) { value_ = cast(bit) b;} this( int b ) { value_ = cast(bit) b;} this( double b ) { value_ = cast(bit) b;} } int main() { bool b = new bool(5.01); printf("%b",b.value_); printf(\n); return 0; } On the default arguments issue: will there be in the future support for default parameters in templates and/or functions.
Jan 24 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Roel Mathys" <roel.mathys yucom.be> wrote in message
news:buvsk3$1fii$1 digitaldaemon.com...
 On the default arguments issue: will there be in the future support for
 default parameters in templates and/or functions.

It isn't really necessary, since D supports function overloading and class template overloading.
Jan 25 2004
parent Roel Mathys <roel.mathys yucom.be> writes:
Walter wrote:

 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:buvsk3$1fii$1 digitaldaemon.com...
 
On the default arguments issue: will there be in the future support for
default parameters in templates and/or functions.

It isn't really necessary, since D supports function overloading and class template overloading.

yes, simply forwarding an overloaded (simpler) version to a more complicated version with the default argument(s) filled in will do. it's a matter of making a choice, and that's up to you, I believe :-) bye, roel
Jan 25 2004
prev sibling parent "davepermen" <davepermen hotmail.com> writes:
i would really appreciate it.

for now, we have to write it like this:

int x = abs!(typeof(a))(a);

and similar. this is ugly, and counterproductive. i used the deduction
feature a lot in c++ to easen and streamline my tasks.

one of the biggest features of c++ is the (extendable) casting ability. this
is only nice doable with (partial) type deduction.

there are a lot of others. make_ functions are one, for example.

math functions in general would love it.

"Walter" <walter digitalmars.com> schrieb im Newsbeitrag
news:buv55j$bui$1 digitaldaemon.com...
 "Roel Mathys" <roel.mathys yucom.be> wrote in message
 news:butkgu$13lk$1 digitaldaemon.com...
 Walter,

 a few points, I'll try to get back into the C++ templates, to try to
 search some more differences.
 but upfront:

 - for me is D's syntax better, nicer, not so heavy as in C++
 - D has alias

 - templatised functions
    => C++ : there is some type deduction going on,
             so one does not have to specify all the types

        e.g. template<typename T> f( T t ) { return 2*t; }
             can be invoked with
             f(5);
             instead of
             f<int>f(5);

Right, template argument deduction for function templates is something D templates don't do. I know how to do it (having implemented it for C++!), but I'm not sure it belongs in D.

Jan 25 2004
prev sibling parent reply "Matthias Spycher" <matthias coware.com> writes:
I don't consider myself an expert and I haven't had the time to investigate
D's template mechanisms in detail. But based on what I've seen here so far:

I agree with Roel that the syntax is definitely a step forward from C++.

The ability to specialize templates is critical. D supports this and also
allows for the specification of bounds on type parameters (at least that's
how I understand it), e.g. template TFoo (T : A) {}, where T has to be
type-compatible with A. I miss this in C++. Java has it in 1.5.

Alias parameters are unique to D and I expect to see quite a few
unanticipated uses of this feature in the future. I hope it doesn't open up
a can of worms. You've mentioned you won't support ADL. If you supported
default arguments to alias parameters, could they be used to inject symbols
from the scope of instantiation into the template definition thereby
overriding the defaults resolved in the scope of definition? In any case,
with the introduction of a real module system and the corresponding
import/export mechanisms, I think you are on the right track here.

Do you support lazy instantiation of template members based on the use of
those members? Or do you regard this as an implementation detail? Or do you
always expect the complete structure to be instantiated, even when only
parts of the template are used?

Matthias

"Walter" <walter digitalmars.com> wrote in message
news:buqk0s$24n9$1 digitaldaemon.com...
 Since you're very familiar with this, I'd be interested in your take on
 whether D's template syntax and semantics improves on it or not, and why.

 have the 2nd book, but not the first.) D templates  *will* go under the
 microscope by the C++ template experts sooner or later, and I'd rather get
 the critiques of it sooner!

Jan 24 2004
parent "Walter" <walter digitalmars.com> writes:
"Matthias Spycher" <matthias coware.com> wrote in message
news:buvbv7$m38$1 digitaldaemon.com...
 The ability to specialize templates is critical. D supports this and also
 allows for the specification of bounds on type parameters (at least that's
 how I understand it), e.g. template TFoo (T : A) {}, where T has to be
 type-compatible with A. I miss this in C++. Java has it in 1.5.

D class templates can also be overloaded, a feature missing from C++.
 Alias parameters are unique to D and I expect to see quite a few
 unanticipated uses of this feature in the future. I hope it doesn't open

 a can of worms.

You're right in that I'm not sure where that will lead. It will be fun to find out, though. Certainly, one can write some really strange templates with it.
 You've mentioned you won't support ADL.

ADL is a hack that is only needed if free operator overloads are supported. But ADL also leads to the C++ export disaster. It won't help D if it is unimplementable <g>.
 If you supported
 default arguments to alias parameters, could they be used to inject

 from the scope of instantiation into the template definition thereby
 overriding the defaults resolved in the scope of definition?

Yes.
 In any case,
 with the introduction of a real module system and the corresponding
 import/export mechanisms, I think you are on the right track here.

 Do you support lazy instantiation of template members based on the use of
 those members? Or do you regard this as an implementation detail? Or do

 always expect the complete structure to be instantiated, even when only
 parts of the template are used?

It always instantiates the whole thing. I suspect the lazy instantiation feature of C++ is really a hack to get around some syntax anomalies. I'm going to see how things work out with D, it may not need it.
Jan 25 2004
prev sibling parent Roel Mathys <roel.mathys yucom.be> writes:
This is a first shot at implementing typelist-templates in D (I 
pickpocketed it from C++).
I don't know if templates in D are meant to work this way.

It does compile, but results are not completely satisfactionary.

In the main() body I indicated case1 and case2,
changing the sequence of the two printf statements changes the results.
Case3 just doesn't work, I guess compiler doesn't detect the 
compile-time constants.

I don't know if I made an error, or did something else wrong. And above 
that I'm still working myself slowly into D.

bye,
roel


/+ -------------------------------------------------- +/
class StopType { alias StopType Tail; }

template isStopType( alias T )
{
	const int value = 0;
}

template isStopType( T : StopType )
{
	const int value = 1;
}

template L(T1, alias T2)
{
	alias T1 Head;
	alias T2 Tail;
}

template L(T)
{
	alias T Head;
	alias StopType Tail;
}

template length( alias TL )
{
	template Help( alias TL2 , int i : 1 )
	{
		const int value = 1;
	}
	template Help( alias TL2 , int i : 0 )
	{
		const int value = 1 + Help!( TL2.Tail
											, isStopType!( TL2.Tail ).value
											).value;
	}
	
	const int value = Help!( TL.Tail
								  , isStopType!( TL.Tail ).value
								  ).value;
}

int main()
{	
	alias L!(int) IL;
	alias L!(double,IL) DIL;
	alias L!(real,DIL) RDIL;

	// case 1
	printf( "%d\n" , length!( DIL).value );
	printf( "%d\n" , length!(  IL).value );
	
	// case 2
	//printf( "%d\n" , length!(  IL).value );
	//printf( "%d\n" , length!( DIL).value );
	
	// does not work
	//printf( "%d\n" , length!(RDIL).value );
	

	return 0;
}
Jan 23 2004