View mode: basic / threaded / horizontal-split · Log in · Help
July 17, 2012
Re: Is this actually supposed to be legal?
On 07/17/2012 10:50 PM, Jonathan M Davis wrote:
> On Tuesday, July 17, 2012 22:36:10 Timon Gehr wrote:
>> On 07/17/2012 07:23 PM, Jonathan M Davis wrote:
>>> On Tuesday, July 17, 2012 14:48:32 David Nadlinger wrote:
>>>> On Tuesday, 17 July 2012 at 05:24:26 UTC, Jonathan M Davis wrote:
>>>>> This code strikes me as being a bug:
>>>>>
>>>>> --------
>>>>> class MyBase(T)
>>>>> {}
>>>>>
>>>>> class MySubA : MyBase!MySubA
>>>>> {}
>>>>>
>>>>> class MySubB : MyBase!MySubB
>>>>> {}
>>>>>
>>>>> void main()
>>>>> {}
>>>>> --------
>>>>
>>>> This pattern is actually quite common in C++ code, and referred
>>>> to as CRTP (curiously recurring template pattern). If you propose
>>>> to kill it, Andrei is going to get mad at you. ;)
>>>
>>> Well, it certainly seems insane to me at first glance - particularly when
>>> you take compile time reflection into account, since the derived classes'
>>> definitions are now effectively recursive (so I suspect that the
>>> situation is worse in D, since C++ doesn't have conditional compliation
>>> like D does).
>> The fact that it is allowed does not make the compiler's job
>> significantly more complicated. It is not important if the type is
>> passed as a template argument or referred to directly from inside the
>> template -- the issues are the same.
>
> The problem is that if you have static ifs and the like in the base class
> which depends on compile time reflection of the derived class, you effectively
> have a recursive template definition. e.g.
>
> class MyBase(T)
> {
>   static if(is(typeof(T.func())))
>   {
>   int func() { return 42; }
>   }
> }
>
> - Jonathan M Davis

This issue is unrelated to CRTP. (also, you probably want to negate
that static if condition, otherwise the code is valid and poses no
challenge to a compiler.)

class MyBase{
  static if(!is(typeof(T.func())))
    int func() { return 42; }
}

class T : MyBase { }
July 17, 2012
Re: Is this actually supposed to be legal?
On Tuesday, 17 July 2012 at 20:50:41 UTC, Jonathan M Davis wrote:
> The problem is that if you have static ifs and the like in the 
> base class
> which depends on compile time reflection of the derived class, 
> you effectively
> have a recursive template definition. e.g.
>
> class MyBase(T)
> {
>  static if(is(tyepeof(T.func())))
>  {
>  int func() { return 42; }
>  }
> }

I don't see how this would be any different than, say, using 
__traits(derivedMembers, typeof(this)) in a struct/class 
declaration.

That being said, I have never used CRTP in D so far, since 
template mixins seem to be the better choice in almost all 
situations.

David
July 17, 2012
Re: Is this actually supposed to be legal?
On Tuesday, July 17, 2012 23:11:43 Timon Gehr wrote:
> This issue is unrelated to CRTP. (also, you probably want to negate
> that static if condition, otherwise the code is valid and poses no
> challenge to a compiler.)

It's not that it makes the compiler's life hard. It's the fact that 
conditional compilation relies on state that doesn't exist yet. It's messed up 
to be checking whether an object defines something when you're in the middle of 
defining that object.

Now, as David N. points out in another post, this isn't exactly the only case 
of that. You can make a templated type do it to itself via something like 
__traits(derivedMembers, typeof(this)), but in this case, you're doing it on a 
template argument which may or may not be a derived class (though presumably 
is).

So, in any case, it's a problem in that you do have to be careful about doing 
conditional compilation based on the type, since it's in the middle of being 
defined, but that's not necessarily enough to merit getting rid of the feature 
(especially since you can have essentially the same problem even without a 
base class).

- Jonathan M Davis
July 18, 2012
Re: Is this actually supposed to be legal?
> That being said, I have never used CRTP in D so far, since template
mixins seem to be the better choice in almost all situations.

FWIW, CRTP is the main reason I used classes in Pegged, to allow grammar
rules to refer to themselves. My earlier attempts with structs did not work.

So, given a grammar rule like:

Expr <- '(' Expr ')' / ...

I use:

class Expr : Or! (Sequence!(Literal!("("), Expr, Literal!(")")) , ...)
{ ... }

As you can see, class Expr refer to itself while it's not defined yet. It's
the main use I've found for this idiom. Many C++ parsers use the same trick
and I was particularly glad to see it worked in D too.

Most of the times I use mixins, but could not find a way to do the same
recursive rule definition with them.

IIRC, I talk a bit about the CRTP in my tutorial on D templates , on Github.

Philippe
July 18, 2012
Re: Is this actually supposed to be legal?
On Tuesday, 17 July 2012 at 23:38:04 UTC, Jonathan M Davis wrote:
> It's not that it makes the compiler's life hard. It's the fact 
> that
> conditional compilation relies on state that doesn't exist yet. 
> It's messed up
> to be checking whether an object defines something when you're 
> in the middle of
> defining that object.
>
> [snip]
>
> - Jonathan M Davis

Well, while you "can" do it in C++ as the "Curiously Recursive 
Template Pattern" (particularly popular way of implementing the 
singleton pattern BTW), you can't just do anything you feel like 
doing with it.

If I remember correctly, in C++, you can't access any of T's 
members, or create any (stack) instances of T, or (I think) call 
T's any of T's static members, because "T is not correctly formed 
yet".

Did you try anything more advanced? For example, this outright 
_crashes_ my (r)dmd:

--------
class MyBase(T)
{
  int a = T.hello();
}

class MySubA : MyBase!MySubA
{
static int hello(){return 0;}
}
--------
I'm not entirely sure how valid the comparison with C++'s CRTP 
is, because D's classes are actually pointer to implementation, 
but I think it is a safe bet that what C++ can't do, neither can 
D.
July 18, 2012
Re: Is this actually supposed to be legal?
On 07/18/2012 11:08 PM, monarch_dodra wrote:
> On Tuesday, 17 July 2012 at 23:38:04 UTC, Jonathan M Davis wrote:
>> It's not that it makes the compiler's life hard. It's the fact that
>> conditional compilation relies on state that doesn't exist yet. It's
>> messed up
>> to be checking whether an object defines something when you're in the
>> middle of
>> defining that object.
>>
>> [snip]
>>
>> - Jonathan M Davis
>
> Well, while you "can" do it in C++ as the "Curiously Recursive Template
> Pattern" (particularly popular way of implementing the singleton pattern
> BTW), you can't just do anything you feel like doing with it.
>
> If I remember correctly, in C++, you can't access any of T's members, or
> create any (stack) instances of T, or (I think) call T's any of T's
> static members, because "T is not correctly formed yet".
>
> Did you try anything more advanced? For example, this outright _crashes_
> my (r)dmd:
>
> --------
> class MyBase(T)
> {
>     int a = T.hello();
> }
>
> class MySubA : MyBase!MySubA
> {
>     static int hello(){return 0;}
> }
> --------

Well, that is a bug.

> I'm not entirely sure how valid the comparison with C++'s CRTP is,
> because D's classes are actually pointer to implementation,  but I think
> it is a safe bet that what C++ can't do, neither can D.

Careful there. D allows forward references. This is all supposed to work 
in D. (but DMD is poor when it comes to tricky symbol lookup tasks.)
July 18, 2012
Re: Is this actually supposed to be legal?
On 07/18/2012 01:37 AM, Jonathan M Davis wrote:
> On Tuesday, July 17, 2012 23:11:43 Timon Gehr wrote:
>> This issue is unrelated to CRTP. (also, you probably want to negate
>> that static if condition, otherwise the code is valid and poses no
>> challenge to a compiler.)
>
> It's not that it makes the compiler's life hard. It's the fact that
> conditional compilation relies on state that doesn't exist yet. It's messed up
> to be checking whether an object defines something when you're in the middle of
> defining that object.
> ...

Declarations in D are declarative. There is no notion of state.
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home