www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - playing around with D

reply Carsten Scharfenberg <cathune_public web.de> writes:
Hello,

I just downloaded D and now I'm playing around a bit. My oppinion about D is
more or the same as every body else's: D is great - but why does this or that
feature not work that am I used to from C++... I think that this is just normal
for a new langue :-).
Anyway I have a couple of questions that arose when I had a look into std.bind.
I'm using  dmd v1.007 and gdc v0.22 on Linux.


1.

the following behaviour I do not understand:


struct TupleContainer( T... )
{
    alias T tuple;

    template append( X )
    {
        alias TupleContainer!( T, X )   append;
    }
}

template UseAppend( /* alias */ TC )
{
    alias TC.append!( int )   UseAppend;
}


void main()
{
    writefln( typeid( TupleContainer!().append!( int ) ) ); // Ok
    writefln( typeid( UseAppend!( TupleContainer!() ) ) );  // Error
}



Error Message:
test.d(xxx): Error: template identifier append is not a member of TC
test.d(xxx): template instance test.UseAppend!(TupleContainer!() ) error
instantiating

If I uncomment the alias befor TC everything works fine - why?
As TC is of type TupleContainer!() which has the member "append" (more
precisely: the named template "append" - I'm not sure if this acounts as a
member) I would presume this should work without the alias.



2.

The second point seems to be a compiler bug - but correct me if I'm wrong:



template isTupleContainer( T )
{
    static if( is( typeof( T.tuple ) ) )
    {
        static if( is( T == TupleContainer!( T.tuple ) ) )
            static const bool isTupleContainer = true;
        else
            static const bool isTupleContainer = false;
    }
    else
        static const bool isTupleContainer = false;
}

template DoSomething( T )
{
    alias T.tuple  OrigTuple;
    
    alias int Result;
}

template AssertTest( T )
{
    static assert( isTupleContainer!( T ) );
    
    alias DoSomething!( T ).Result    AssertTest;
/*      alias int AssertTest;*/
}

void main()
{
    /*
     * this is perfectly fine and prints false
     */
    writefln( typeid( isTupleContainer!( int ) ) );
    
    /*
     * this should trigger the assert in AssertTest - but it doesn't,
     * a compiler error is emitted instead.
     */
    writefln( typeid( AssertTest!( int ) ) );
}


Error Message:
test.d(xxx): Error: no property 'tuple' for type 'int'
test.d(xxx): Error: T.tuple is used as a type
test.d(xxx): template instance test.DoSomething!(int) error instantiating


isTupleContainer checks, of course, if T is a TupleContainer. This works fine in
the main function - but in AssertTest its result seems always to be true
so that the assert is never triggered.
The assert is triggered in the correct way, if I (1) swap comments for both
assert lines in AssertTest, or (2) outcomment the first alias line in
DoSomething! This is very strange...



3.

Regarding the prevois isTupleContainer template it would be nice to have
a more general possiblity to check if a type is an arbitary instantiation of a
given template. It's easy to check for a special instantiation:



struct Type( T )
{
    ...
}

template CheckType( T )
{
    static if( is( T == Type( int ) ) )
        static const int CheckType = true;
    else
        static const int CheckType = false;
}


it is also possible to do the following:


template isInstantiation( T1, alias T2 )
{
    static if( is( T1 t == T2( t ) ) )
        static const int isInstantiation = true;
    else
        static const int isInstantiation = false;
}


this checks for an arbitary instantiation of an arbitary template - but only if
T2 has exactly one template parameter. I'm looking for a possiblity to do this
check for an arbitary number of template parameters.



4.

By the way: what is the difference between
static const int        and         const int ?
Both variants work in the examples above.

Regards,
Carsten Scharfenberg
Mar 05 2007
next sibling parent Carsten Scharfenberg <cathune_public web.de> writes:
Oops, don't know why I posted this two times...
Also there was a little error in my post:

...
 
 template AssertTest( T )
 {
     static assert( isTupleContainer!( T ) );
     
     alias DoSomething!( T ).Result    AssertTest;
 /*      alias int AssertTest;*/
 }
 

...
 The assert is triggered in the correct way, if I (1) swap comments for both
 assert lines in AssertTest, or (2) outcomment the first alias line in
 DoSomething! This is very strange...

Correct is: The assert is triggered in the correct way, if I (1) swap comments for both *>alias<* lines in AssertTest, or (2) outcomment the first alias line in DoSomething! This is very strange...
Mar 05 2007
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Carsten Scharfenberg wrote:
 Hello,
 
 I just downloaded D and now I'm playing around a bit. My oppinion about D is
more or the same as every body else's: D is great - but why does this or that
feature not work that am I used to from C++... I think that this is just normal
for a new langue :-).
 Anyway I have a couple of questions that arose when I had a look into
std.bind. I'm using  dmd v1.007 and gdc v0.22 on Linux.
 
 
 1.
 
 the following behaviour I do not understand:
 
 
 struct TupleContainer( T... )
 {
     alias T tuple;
 
     template append( X )
     {
         alias TupleContainer!( T, X )   append;
     }
 }
 
 template UseAppend( /* alias */ TC )
 {
     alias TC.append!( int )   UseAppend;
 }
 
 
 void main()
 {
     writefln( typeid( TupleContainer!().append!( int ) ) ); // Ok
     writefln( typeid( UseAppend!( TupleContainer!() ) ) );  // Error
 }
 
 
 
 Error Message:
 test.d(xxx): Error: template identifier append is not a member of TC
 test.d(xxx): template instance test.UseAppend!(TupleContainer!() ) error
 instantiating
 
 If I uncomment the alias befor TC everything works fine - why?
 As TC is of type TupleContainer!() which has the member "append" (more
precisely: the named template "append" - I'm not sure if this acounts as a
member) I would presume this should work without the alias.

I would expect it to work, too. Don't be too surprised if you find template bugs -- the D template system is much more extensive than for C++, and new features have been added at a terrifying pace.
 
 2.
 
 The second point seems to be a compiler bug - but correct me if I'm wrong:
 
 
 
 template isTupleContainer( T )
 {
     static if( is( typeof( T.tuple ) ) )
     {
         static if( is( T == TupleContainer!( T.tuple ) ) )
             static const bool isTupleContainer = true;
         else
             static const bool isTupleContainer = false;
     }
     else
         static const bool isTupleContainer = false;
 }
 
 template DoSomething( T )
 {
     alias T.tuple  OrigTuple;
     
     alias int Result;
 }
 
 template AssertTest( T )
 {
     static assert( isTupleContainer!( T ) );
     
     alias DoSomething!( T ).Result    AssertTest;
 /*      alias int AssertTest;*/
 }
 
 void main()
 {
     /*
      * this is perfectly fine and prints false
      */
     writefln( typeid( isTupleContainer!( int ) ) );
     
     /*
      * this should trigger the assert in AssertTest - but it doesn't,
      * a compiler error is emitted instead.
      */
     writefln( typeid( AssertTest!( int ) ) );
 }
 
 
 Error Message:
 test.d(xxx): Error: no property 'tuple' for type 'int'
 test.d(xxx): Error: T.tuple is used as a type
 test.d(xxx): template instance test.DoSomething!(int) error instantiating
 
 
 isTupleContainer checks, of course, if T is a TupleContainer. This works fine
in
 the main function - but in AssertTest its result seems always to be true
 so that the assert is never triggered.
 The assert is triggered in the correct way, if I (1) swap comments for both
 assert lines in AssertTest, or (2) outcomment the first alias line in
 DoSomething! This is very strange...

You're right, something about static assert is a bit weird and doesn't work very well. I stopped relying on it, and use a static if(xxx) { static assert(0, "xxx"); } combination instead.
 3.
 
 Regarding the prevois isTupleContainer template it would be nice to have
 a more general possiblity to check if a type is an arbitary instantiation of a
 given template. It's easy to check for a special instantiation:
 
 
 
 struct Type( T )
 {
     ...
 }
 
 template CheckType( T )
 {
     static if( is( T == Type( int ) ) )
         static const int CheckType = true;
     else
         static const int CheckType = false;
 }
 
 
 it is also possible to do the following:
 
 
 template isInstantiation( T1, alias T2 )
 {
     static if( is( T1 t == T2( t ) ) )
         static const int isInstantiation = true;
     else
         static const int isInstantiation = false;
 }
 
 
 this checks for an arbitary instantiation of an arbitary template - but only if
 T2 has exactly one template parameter. I'm looking for a possiblity to do this
 check for an arbitary number of template parameters.

I was going to post this as a "Question of the Week" question. It can be done with a .mangleof hack, but there ought to be a cleaner way to do it.
 4.
 
 By the way: what is the difference between
 static const int        and         const int ?
 Both variants work in the examples above.

I don't know what 'static const int' means. IMHO, it should be a compiler error, since you're mixing storage classes (unlike C++, in D, 'const' really means constant). Use 'const int' instead.
Mar 05 2007
next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Don Clugston wrote:
 Carsten Scharfenberg wrote:
 4.

 By the way: what is the difference between
 static const int        and         const int ?
 Both variants work in the examples above.

I don't know what 'static const int' means. IMHO, it should be a compiler error, since you're mixing storage classes (unlike C++, in D, 'const' really means constant). Use 'const int' instead.

"static" is ignored in the global scope. And note that "const"s can have different values per instance: class X { const int member; this(int x) { member = x; } //... } This is still allowed. Don't ask me why, I think it's confusing. L.
Mar 05 2007
parent Don Clugston <dac nospam.com.au> writes:
Lionello Lunesu wrote:
 Don Clugston wrote:
 Carsten Scharfenberg wrote:
 4.

 By the way: what is the difference between
 static const int        and         const int ?
 Both variants work in the examples above.

I don't know what 'static const int' means. IMHO, it should be a compiler error, since you're mixing storage classes (unlike C++, in D, 'const' really means constant). Use 'const int' instead.

"static" is ignored in the global scope.

I think that's like: public protected private import std.stdio; which also compiles. And note that "const"s can have
 different values per instance:
 
 class X {
   const int member;
   this(int x) { member = x; }
 //...
 }
 
 This is still allowed. Don't ask me why, I think it's confusing.

That's not a const. It has almost nothing in common with const int, except an unfortunate sharing of the syntax. It should be written 'final int member'. I was deliberately ignoring that aberration.
Mar 05 2007
prev sibling next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Don Clugston wrote:
 Carsten Scharfenberg wrote:
 [snip]

 If I uncomment the alias befor TC everything works fine - why?
 As TC is of type TupleContainer!() which has the member "append" (more
 precisely: the named template "append" - I'm not sure if this acounts
 as a member) I would presume this should work without the alias.

I would expect it to work, too. Don't be too surprised if you find template bugs -- the D template system is much more extensive than for C++, and new features have been added at a terrifying pace.

I can't see why it *should* work. The way I've always thought about it is that templates are parameterised namespaces. Since (/*alias*/ TC) is a type parameter, it makes no sense to pass in a namespace, whereas (alias TC) *does* since it's an alias to an arbitrary symbol. I dunno; maybe it's just my way of rationalising it :P -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 05 2007
prev sibling parent Sean Kelly <sean f4.ca> writes:
Don Clugston wrote:
 Carsten Scharfenberg wrote:
 Hello,

 I just downloaded D and now I'm playing around a bit. My oppinion 
 about D is more or the same as every body else's: D is great - but why 
 does this or that feature not work that am I used to from C++... I 
 think that this is just normal for a new langue :-).
 Anyway I have a couple of questions that arose when I had a look into 
 std.bind. I'm using  dmd v1.007 and gdc v0.22 on Linux.


 1.

 the following behaviour I do not understand:


 struct TupleContainer( T... )
 {
     alias T tuple;

     template append( X )
     {
         alias TupleContainer!( T, X )   append;
     }
 }

 template UseAppend( /* alias */ TC )
 {
     alias TC.append!( int )   UseAppend;
 }


 void main()
 {
     writefln( typeid( TupleContainer!().append!( int ) ) ); // Ok
     writefln( typeid( UseAppend!( TupleContainer!() ) ) );  // Error
 }



 Error Message:
 test.d(xxx): Error: template identifier append is not a member of TC
 test.d(xxx): template instance test.UseAppend!(TupleContainer!() ) error
 instantiating

 If I uncomment the alias befor TC everything works fine - why?
 As TC is of type TupleContainer!() which has the member "append" (more 
 precisely: the named template "append" - I'm not sure if this acounts 
 as a member) I would presume this should work without the alias.

I would expect it to work, too. Don't be too surprised if you find template bugs -- the D template system is much more extensive than for C++, and new features have been added at a terrifying pace.
 2.

 The second point seems to be a compiler bug - but correct me if I'm 
 wrong:



 template isTupleContainer( T )
 {
     static if( is( typeof( T.tuple ) ) )
     {
         static if( is( T == TupleContainer!( T.tuple ) ) )
             static const bool isTupleContainer = true;
         else
             static const bool isTupleContainer = false;
     }
     else
         static const bool isTupleContainer = false;
 }

 template DoSomething( T )
 {
     alias T.tuple  OrigTuple;
         alias int Result;
 }

 template AssertTest( T )
 {
     static assert( isTupleContainer!( T ) );
         alias DoSomething!( T ).Result    AssertTest;
 /*      alias int AssertTest;*/
 }

 void main()
 {
     /*
      * this is perfectly fine and prints false
      */
     writefln( typeid( isTupleContainer!( int ) ) );
         /*
      * this should trigger the assert in AssertTest - but it doesn't,
      * a compiler error is emitted instead.
      */
     writefln( typeid( AssertTest!( int ) ) );
 }


 Error Message:
 test.d(xxx): Error: no property 'tuple' for type 'int'
 test.d(xxx): Error: T.tuple is used as a type
 test.d(xxx): template instance test.DoSomething!(int) error instantiating


 isTupleContainer checks, of course, if T is a TupleContainer. This 
 works fine in
 the main function - but in AssertTest its result seems always to be true
 so that the assert is never triggered.
 The assert is triggered in the correct way, if I (1) swap comments for 
 both
 assert lines in AssertTest, or (2) outcomment the first alias line in
 DoSomething! This is very strange...

You're right, something about static assert is a bit weird and doesn't work very well. I stopped relying on it, and use a static if(xxx) { static assert(0, "xxx"); } combination instead.
 3.

 Regarding the prevois isTupleContainer template it would be nice to have
 a more general possiblity to check if a type is an arbitary 
 instantiation of a
 given template. It's easy to check for a special instantiation:



 struct Type( T )
 {
     ...
 }

 template CheckType( T )
 {
     static if( is( T == Type( int ) ) )
         static const int CheckType = true;
     else
         static const int CheckType = false;
 }


 it is also possible to do the following:


 template isInstantiation( T1, alias T2 )
 {
     static if( is( T1 t == T2( t ) ) )
         static const int isInstantiation = true;
     else
         static const int isInstantiation = false;
 }


 this checks for an arbitary instantiation of an arbitary template - 
 but only if
 T2 has exactly one template parameter. I'm looking for a possiblity to 
 do this
 check for an arbitary number of template parameters.

I was going to post this as a "Question of the Week" question. It can be done with a .mangleof hack, but there ought to be a cleaner way to do it.

Doesn't this work? template isInstantiation( alias T, Args... ) { static if( is( T( Args ) ) ) static const int isInstantiation = true; else static const int isInstantiation = false; } I haven't tried it, but I'd expect it to. Sean
Mar 05 2007