Thread overview
A couple of questions
May 13, 2009
Sam Hu
May 13, 2009
BCS
May 13, 2009
Sam Hu
May 13, 2009
John C
May 13, 2009
Simen Kjaeraas
May 13, 2009
Robert Fraser
May 13, 2009
Sam Hu
May 13, 2009
Hello,

For the given example below,

E1:
template Chain(R...) if (allSatisfy!(isInputRange, R))
{
    static if (R.length > 1)
        alias ChainImpl!(R) Chain;
    else
        alias R[0] Chain;
}
Q1: What's *if* statement doing right after the template definite?I can guess what the purpose is but I can not find the answer from the spec.

E2:
template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    {
        R r;             // can define a range object
        if (r.empty) {}  // can test for empty
        r.popFront;          // can invoke next
        auto h = r.front; // can get the front of the range
    }()));
}

Q2:What's the logic inside the enum...{} blocks?
Q3:The *typeof* expression here. is it an anonymous function/delegate which return a bool value?If not,how come there is a () pairs appeared right after the enum{}blocks?If yes,shouldn't the () pairs appear before the last *)* ?

It would be grateful if anybody can help.

Regards,
Sam
May 13, 2009
Hello Sam,

> Hello,
> 
> For the given example below,
> 
> E1:
> template Chain(R...) if (allSatisfy!(isInputRange, R))
> {
> static if (R.length > 1)
> alias ChainImpl!(R) Chain;
> else
> alias R[0] Chain;
> }
> Q1: What's *if* statement doing right after the template definite?I
> can guess what the purpose is but I can not find the answer from the
> spec.
> 
> E2:
> template isInputRange(R)
> {
> enum bool isInputRange = is(typeof(
> {
> R r;             // can define a range object
> if (r.empty) {}  // can test for empty
> r.popFront;          // can invoke next
> auto h = r.front; // can get the front of the range
> }()));
> }
> Q2:What's the logic inside the enum...{} blocks?

That is an odd construct and not an enum block, breaking it into pieces:

enum bool isInputRange = SomeBoolExp;

SomeBoolExp:  // true if SomeExp is a valid expression
   is(typeof(SomeExp))

SomeExp:  // a function call
   SomeFnExp()

SomeFnExp: // a delegate literal
   {
      R r;             // can define a range object
      if (r.empty) {}  // can test for empty
      r.popFront;          // can invoke next
      auto h = r.front; // can get the front of the range
   }


> Q3:The *typeof* expression here. is it an anonymous function/delegate
> which return a bool value?If not,how come there is a () pairs appeared
> right after the enum{}blocks?If yes,shouldn't the () pairs appear
> before the last *)* ?
> It would be grateful if anybody can help.

see above

> 
> Regards,
> Sam


May 13, 2009
Thanks.The construct is clear now.

Still leaves Q1,that is ,the *if* expression after the template definition,I want to learn more about the usage,where can I find more information?

and one more question here:
Q4.In the delegate somFnExp:front(),popFront,empty() are all not defined??Anyway it is not an interface ,so why it is allowed?

Thanks for help.
Sam
May 13, 2009
Sam Hu Wrote:

> Thanks.The construct is clear now.
> 
> Still leaves Q1,that is ,the *if* expression after the template definition,I want to learn more about the usage,where can I find more information?

It is in the spec: http://www.digitalmars.com/d/2.0/template.html#Constraint
May 13, 2009
Sam Huwrote:

> Q4.In the delegate somFnExp:front(),popFront,empty() are all not defined??Anyway it is not an interface ,so why it is allowed?

Basically, is(typeof(X)) is D magic.

One could interpret it as 'is X a valid type', or perhaps more
correctly as 'does X compile'. So if SomeFnExp does something it
is not allowed to (e.g. call popFront on something that has no
popFront), it will return false.

If I were to write this code without is(typeof()) around it:

 R r;
 if (r.empty) {}
 r.popFront;
 auto h = r.front;

It might seem a strange piece of code, but there is nothing
inherently wrong with it. empty, popFront and front are
expected members of R, and will give a compilation error if R
does not follow the interface (note: not as in a D interface, but
as in exposing the correct functions to the outside world).


--
 Simen
May 13, 2009
Simen Kjaeraas wrote:
> Sam Huwrote:
> 
>> Q4.In the delegate somFnExp:front(),popFront,empty() are all not defined??Anyway it is not an interface ,so why it is allowed?
> 
> Basically, is(typeof(X)) is D magic.
> 
> One could interpret it as 'is X a valid type', or perhaps more
> correctly as 'does X compile'. So if SomeFnExp does something it
> is not allowed to (e.g. call popFront on something that has no
> popFront), it will return false.
> 
> If I were to write this code without is(typeof()) around it:
> 
>  R r;
>  if (r.empty) {}
>  r.popFront;
>  auto h = r.front;
> 
> It might seem a strange piece of code, but there is nothing
> inherently wrong with it. empty, popFront and front are
> expected members of R, and will give a compilation error if R
> does not follow the interface (note: not as in a D interface, but
> as in exposing the correct functions to the outside world).
> 
> 
> -- 
>  Simen

IOW,

is(typeof({ XXXXXX }())

Evaluates to a boolean meaning "does a function containing XXXXXX compile". Its purpose here is to find out if r has "empty", "popFront" and "front". This is placed inside a template that has one member that is the name of the template, so it ends up that:

isInputRange!(R)

just becomes a boolean that's true if R has "empty", "popFront", and "front", and false if it doesn't.

... C++ template hacks are worse. Really. Usually.
May 13, 2009
Hi All,

Thank you so much! It really helps!

Regards,
Sam