January 24, 2006
> Why is meta programming being done with templates? I have seen a number of vary nice things done with that technique but it seems to me to be a terribly convoluted way to go about it. Why not place some of the functionality right in the language it's self?

If this were the case, perhaps reflection API could be added to the standard library rather than the language core.

-Craig


January 24, 2006
Craig Black wrote:
>> Why is meta programming being done with templates? I have seen a number of vary nice things done with that technique but it seems to me to be a terribly convoluted way to go about it. Why not place some of the functionality right in the language it's self?
> 
> If this were the case, perhaps reflection API could be added to the standard library rather than the language core.

The library will support whatever it can, given language support.  I'm already planning a reflection module for Ares.


Sean
January 24, 2006
Sean Kelly wrote:
> 
> The library will support whatever it can, given language support.  I'm already planning a reflection module for Ares.

Er, I meant traits module.


Sean
January 24, 2006
> Providing you put the superof alias in your classes, you can already do (since it's legal to derive from Object):
> 
> template ListBaseClass(T)
> {
>   static if( is(T: Object) && !is(T==Object))
>           alias T.superof ListBaseClass;
>   else alias Object ListBaseClass;
> }
> 
> template List(T)
> {
>   class List : ListBaseClass!(T) {
>    ....
>   }
> }
> 
>>
>> or
>>
>> class Foo(T) {
>>     static if (is(T:Serializable)) {
>>         this class : Serializable;
>>     } else {
>>         this class : PartiallySerializable;
>>     }
>> }
> 
> 
> template FooBaseClass(T)
> {
>   static if( is(T: Serializable))
>           alias Serializable FooBaseClass;
>   else alias PartiallySerializable FooBaseClass;
> }
> 
> class Foo(T) : public FooBaseClass!(T)
> {
>   ...
> }

OK then, I guess my problem is solvable already.. You really are the man when it comes to D templates :)


xs0
January 24, 2006
In article <dr5ml8$29vf$1@digitaldaemon.com>, xs0 says...
>
>OK then, I guess my problem is solvable already.. You really are the man when it comes to D templates :)
>

I do believe you mean "Template Ninja".  Seriously.  The man enacts strikes of template ninjitsu with an unmatched level of cunning and skill.

- EricAnderton at yahoo
January 24, 2006
Sean Kelly wrote:
> James Dunne wrote:
> 
>>
>> Compile-time code generation!  Another one of those great features that I've been kicking around for my own little language.  This gives me a few ideas for syntax.  I like your thinking!  Keep it up.
> 
> 
> It certainly beats the heck out of merely hoping that the compiler will inline recursive function calls, which is how this is normally done. But it would need to be a bit more flexible to be ideal.  For example, I'd like to be able to iterate across typelists this way, to automate factory class generation.
> 
> 
> Sean

Don Clugston wrote:
>
> I think there are so many meta programming possibilities that an
> enormous number of features would need to be added to the language.
> But it's definitely worth considering which things are currently
> convoluted, and whether simplifications are possible.
>
> The example you provide is currently not possible at all with meta
> programming:
>

Examples please? What other functionality would be useful? What other meta programming tasks are commonly needed that templates can't do? I think there is a need for a whole set of statement (meta-statements?) along this line.

I am still wondering why templates are being used for this. Is it just that they are the only tool at hand?
January 24, 2006
BCS wrote:
> Sean Kelly wrote:
>> James Dunne wrote:
>>
>>> Compile-time code generation!  Another one of those great features that I've been kicking around for my own little language.  This gives me a few ideas for syntax.  I like your thinking!  Keep it up.
>>
>> It certainly beats the heck out of merely hoping that the compiler will inline recursive function calls, which is how this is normally done. But it would need to be a bit more flexible to be ideal.  For example, I'd like to be able to iterate across typelists this way, to automate factory class generation.
> 
> Don Clugston wrote:
>  >
>  > I think there are so many meta programming possibilities that an
>  > enormous number of features would need to be added to the language.
>  > But it's definitely worth considering which things are currently
>  > convoluted, and whether simplifications are possible.
>  >
>  > The example you provide is currently not possible at all with meta
>  > programming:
> 
> Examples please? What other functionality would be useful? What other meta programming tasks are commonly needed that templates can't do? I think there is a need for a whole set of statement (meta-statements?) along this line.
>
> I am still wondering why templates are being used for this. Is it just that they are the only tool at hand?

Pretty much.  The goal is to be able to generate optimal code at compile-time with minimal user effort... and to do so using language features instead of a fancy IDE.  There have been a number of books written on the subject, but my two favorites are "Modern C++ Design" by Alexander Alexandrescu and "Generative Programming" by Czarnecki and Eisenecker.  For a practical example, here's some code I posted to comp.lang.c++.moderated about five years ago (I love google):

--------------------------------------------------------------------------------

This is the final version of my test code.  The idea is that I wanted
to be able to specify the allowable classes a factory could construct
at the time of declaration -- I've got a library class that needs a
list of acceptable pre-defined classes which it can construct for its
own internal use.  To this end, I didn't want to force the user to
call register methods or any other code-based means of specifying
factory classes.

I used Loki to construct a factory to do this... its only downside is
that the nature of the function expansion means that every call will
scan the list in linear time.  I've got a map-based version mostly
built, but it will need to hold instances of the classes and call a
Clone method, which requires memory overhead I'd currently rather
avoid.

In any case, I hope someone finds this useful.  Just a bit more
exploration of some nifty things templates can do:

////////////////////////////////////////////////////////////////////////////////

#include <string>
#include <iostream>
#include <Typelist.h>

////////////////////////////////////////////////////////////////////////////////

template<const char** Name, class Type>
struct index_pair
{
    static const char*  name;
    typedef Type        type;

};

template<const char** Name, class Type>
const char* index_pair<Name,Type>::name = *Name;

////////////////////////////////////////////////////////////////////////////////

template<class Base, class TList, int Default, int ListSize =
Loki::TL::Length<TList>::value>
struct MyFactory
{
    inline static Base* MakeNew( int index = Default )
    {
        assert( index < ListSize );
        if( index == (ListSize-1) )
            return( new
Loki::TL::TypeAt<TList,ListSize-1>::Result::type() );
        else
            return( MyFactory<Base,TList,Default,ListSize-1>::MakeNew(
index ) );
    }

    inline static Base* MakeNew( const std::string& name )
    {
        if( name == Loki::TL::TypeAt<TList,ListSize-1>::Result::name )
            return( new
Loki::TL::TypeAt<TList,ListSize-1>::Result::type() );
        else
            return( MyFactory<Base,TList,Default,ListSize-1>::MakeNew(
name ) );
    }

};

template<class Base, class TList, int Default>
struct MyFactory<Base,TList,Default,0>
{
    inline static Base* MakeNew( int index = Default )
    {
        return( NULL );
    }

    inline static Base* MakeNew( const std::string& name )
    {
        return( NULL );
    }

};

////////////////////////////////////////////////////////////////////////////////

struct base
{
    virtual ~base() {}
    virtual void operator()() { std::cout << "base\n"; }

};

struct derived1 : public base
{
    virtual void operator()() { std::cout << "derived1\n"; }

};

struct derived2 : public base
{
    virtual void operator()() { std::cout << "derived2\n"; }

};

struct derived3 : public base
{
    virtual void operator()() { std::cout << "derived3\n"; }

};

const char* base_name = "base";
const char* derived1_name = "derived1";
const char* derived2_name = "derived2";
const char* derived3_name = "derived3";

int main( int argc, char **argv )
{
    typedef index_pair<&base_name,base> base_pair;
    typedef index_pair<&derived1_name,derived1> derived1_pair;
    typedef index_pair<&derived2_name,derived2> derived2_pair;
    typedef index_pair<&derived3_name,derived3> derived3_pair;

    typedef MyFactory<base,TYPELIST_4(base_pair,derived1_pair,derived2_pair,derived3_pair),1>
fact;
    base* b1 = fact::MakeNew();
    base* b2 = fact::MakeNew( 0 );
    base* b3 = fact::MakeNew( 1 );
    base* b4 = fact::MakeNew( 2 );
    base* b5 = fact::MakeNew( "base" );
    (*b1)();
    (*b2)();
    (*b3)();
    (*b4)();
    (*b5)();
    return( 0 );

}
January 24, 2006
Sean Kelly wrote:
> BCS wrote:
>> I am still wondering why templates are being used for this. Is it just that they are the only tool at hand?
> 
> 
> Pretty much.  The goal is to be able to generate optimal code at compile-time with minimal user effort... and to do so using language features instead of a fancy IDE.


I'm getting the impression that we're trying to clone the language functionality into the compile-time part. We had a nifty proposal some time ago which, if implemented, might ease the pain.
The idea was to allow a special modifier for functions which would say that they could be evaluated at compile-time. Thus the code would look just like ordinary runtime code, but being executed at compile-time.



-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
January 24, 2006
Sean Kelly wrote:
> 
> I used Loki to construct a factory to do this... its only downside is
> that the nature of the function expansion means that every call will
> scan the list in linear time.  I've got a map-based version mostly
> built, but it will need to hold instances of the classes and call a
> Clone method, which requires memory overhead I'd currently rather
> avoid.

By the way... I'd originally hoped to do this using a switch statement instead of recursion, but this doesn't really work with C++ templates. I'm not sure if it would work with D templates (I'd have to think about it a bit), but something like witheach should make this possible as each case statement could be generated inline.  It would be darn nice to have something like this, as the resulting code would be extremely fast.


Sean
January 24, 2006
Tom S wrote:
> Sean Kelly wrote:
> 
>> BCS wrote:
>>
>>> I am still wondering why templates are being used for this. Is it just that they are the only tool at hand?
>>
>>
>>
>> Pretty much.  The goal is to be able to generate optimal code at compile-time with minimal user effort... and to do so using language features instead of a fancy IDE.
> 
> 
> 
> I'm getting the impression that we're trying to clone the language functionality into the compile-time part. We had a nifty proposal some time ago which, if implemented, might ease the pain.
> The idea was to allow a special modifier for functions which would say that they could be evaluated at compile-time. Thus the code would look just like ordinary runtime code, but being executed at compile-time.
> 
> 
> 

If I'm not mistaken, that was mine =P.  Use the colon operator to differentiate compile-time properties from run-time properties!  Either that or it was my '{%' ... '%}' block idea which was to execute code at compile time (though I never proposed this for D).