Bug in D!!!

EntangledQuanta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Aug 30 14:51:57 PDT 2017


On Wednesday, 30 August 2017 at 21:33:30 UTC, Jonathan M Davis 
wrote:
> On Wednesday, August 30, 2017 20:47:12 EntangledQuanta via 
> Digitalmars-d- learn wrote:
>> This is quite surprising!
>>
>> public struct S(T)
>> {
>>   T s;
>> }
>>
>>
>> interface I
>> {
>>   void Go(T)(S!T s);
>>
>>   static final I New()
>>   {
>>       return new C();
>>   }
>> }
>>
>> abstract class A : I
>> {
>>
>> }
>>
>>
>> class C : A
>> {
>>   void Go(T)(S!T s)
>>   {
>>
>>   }
>> }
>>
>>
>> void main()
>> {
>>   S!int s;
>>   auto c = I.New();
>>
>>   c.Go(s);    // fails!
>>   //(cast(C)c).Go(s);  // Works, only difference is we have 
>> made c
>> an explicit C.
>>
>> }
>>
>> https://dpaste.dzfl.pl/dbc5a0663802
>>
>> Everything works when Go is not templatized(we explicitly make 
>> T
>> an int)
>>
>>
>> This is a blocker for me! Can someone open a ticket?
>
> It is not possible to have a function be both virtual and 
> templated. A function template generates a new function 
> definition every time that it's a called with a new set of 
> template arguments. So, the actual functions are not known up 
> front, and that fundamentally does not work with virtual 
> functions, where the functions need to be known up front, and 
> you get a different function by a look-up for occurring in the 
> virtual function call table for the class. Templates and 
> virtual functions simply don't mix. You're going to have to 
> come up with a solution that does not try and mix templates and 
> virtual functions.
>
> - Jonathan M Davis


I have a finite number of possible values of T, lets say 3. They 
are known at compile time, just because you are or D thinks they 
are not simply means you or D is not trying hard enough. So, 
saying that virtual methods and templates are not compatible is 
wrong. Just because you think they are or D thinks they are means 
you haven't thought about it hard enough.

If I can overload a virtual function to get all my use cases and 
that is all I need then I **should** be able to do it with 
templates. Simple as that, if D can't do that then D needs to be 
enhanced to do so.

e.g.,

class C
{
    Go(Primitive!T)(T t);
}

The compiler can realize that T can only be a primitive, and 
generates all possible combinations of primitives, which is 
finite. This is doable, it is not impossible, regardless of what 
you think. It is equivalent to

class C
{
    Go(Primitive1 t);
    Go(Primitive2 t);
    ...
    Go(PrimitiveN t);
}


In fact, we can use string mixins to generate such code, but it 
doens't save us trouble, which is what templates are suppose to 
do in the first place. Just become someone hasn't implemented 
special cases does not mean it is theoretically impossible to do.

A different syntax would be better

interface I
{
   Go(T in [float, double, int])(T t);
}

class C : I
{
   Go(T in [float, double, int])(T t) { }
}

which the compiler "unrolls" to

interface I
{
   Go(float t);
   Go(double t);
   Go(int t);
}


class C
{
   Go(float t) { }
   Go(double t) { }
   Go(int t) { }
}

Which, is standard D code. There is nothing wrong with 
specializing the most common cases.

The point you are trying to making, and not doing a great job, is 
that the compiler cannot create an unknown set of virtual 
functions from a single templated virtual function. BUT, when you 
realize that is what the problem is, the unknown set is the issue 
NOT templated virtual functions. Make the set known and finite 
somehow then you have a solution, and it's not that difficult. 
Just requires some elbow grease.

Primitives are obviously known at compile time so that is a 
doable special case. Although there will probably be quite a bit 
of wasted space since each primitive will have a function 
generated for it for each templated function, that really isn't 
an issue.

By adding a new syntax in D, we could allow for any arbitrary(but 
known and finite) set to be used

Go(T in [A,B,C])(T t)

Where A,B,C are known types at compile time. This generates 3 
functions and is doable. (should be simple for any D compiler 
genius to add for testing)















More information about the Digitalmars-d-learn mailing list