TypeFunction example: ImplictConvTargets

Stefan Koch uplink.coder at googlemail.com
Tue Oct 6 10:22:44 UTC 2020


On Tuesday, 6 October 2020 at 01:12:01 UTC, Walter Bright wrote:
> On 10/5/2020 2:20 PM, Stefan Koch wrote:
>> Now post it with all transitive dependencies.
>
> I'm not sure how transitive dependencies applies here. A 
> illuminating test case would be helpful.

Okay let me show you the transitive dependencies of the "3 liner" 
suggested by Andrei and executed by Paul Backus.

--- phobos dependencies ---

template ApplyLeft(alias Template, args...)
{
     alias ApplyLeft(right...) = SmartAlias!(Template!(args, 
right));
}

private template SmartAlias(T...)
{
     static if (T.length == 1)
     {
         alias SmartAlias = Alias!T;
     }
     else
     {
         alias SmartAlias = T;
     }
}

alias Alias(alias a) = a;
alias Alias(T) = T;

template Filter(alias pred, TList...)
{
     static if (TList.length < filterExpandFactor)
     {
         mixin(FilterShortCode[TList.length]);
     }
     else
     {
         template MaybeNothing(Q...)
         {
             static if (pred!(Q[0]))
                 alias MaybeNothing = AliasSeq!(Q[0]);
             else
                 alias MaybeNothing = Nothing;
         }

         alias Filter = staticMap!(MaybeNothing, TList);
     }
}

private enum staticMapExpandFactor = 150;
private string generateCases()
{
     string[staticMapExpandFactor] chunks;
     chunks[0] = q{};
     static foreach (enum i; 0 .. staticMapExpandFactor - 1)
             chunks[i + 1] = chunks[i] ~ `F!(Args[` ~ i.stringof ~ 
`]),`;
         string ret = `AliasSeq!(`;
         foreach (chunk; chunks)
             ret ~= `q{alias staticMap = AliasSeq!(` ~ chunk ~ 
`);},`;
         return ret ~ `)`;
         }

         private alias staticMapBasicCases = 
AliasSeq!(mixin(generateCases()));

         template staticMap(alias F, Args...)
         {
             static if (Args.length < staticMapExpandFactor)
                 mixin(staticMapBasicCases[Args.length]);
             else
                 alias staticMap = AliasSeq!(staticMap!(F, Args[0 
.. $ / 2]),
                     staticMap!(F, Args[$ / 2 .. $]));
         }


private alias FilterShortCode = AliasSeq!(
     q{
         alias Filter = Nothing;
     },
     q{
         static if (pred!(TList[0]))
             alias Filter = AliasSeq!(TList[0]);
         else
             alias Filter = Nothing;
     },
     q{
         static if (pred!(TList[0]))
         {
             static if (pred!(TList[1]))
                 alias Filter = AliasSeq!(TList[0], TList[1]);
             else
                 alias Filter = AliasSeq!(TList[0]);
         }
         else
         {
             static if (pred!(TList[1]))
                 alias Filter = AliasSeq!(TList[1]);
             else
                 alias Filter = Nothing;
         }
     },
     q{
         static if (pred!(TList[0]))
         {
             static if (pred!(TList[1]))
             {
                 static if (pred!(TList[2]))
                     alias Filter = AliasSeq!(TList[0], TList[1], 
TList[2]);
                 else
                     alias Filter = AliasSeq!(TList[0], TList[1]);
             }
             else
             {
                 static if (pred!(TList[2]))
                     alias Filter = AliasSeq!(TList[0], TList[2]);
                 else
                     alias Filter = AliasSeq!(TList[0]);
             }
         }
         else
         {
             static if (pred!(TList[1]))
             {
                 static if (pred!(TList[2]))
                     alias Filter = AliasSeq!(TList[1], TList[2]);
                 else
                     alias Filter = AliasSeq!(TList[1]);
             }
             else
             {
                 static if (pred!(TList[2]))
                     alias Filter = AliasSeq!(TList[2]);
                 else
                     alias Filter = Nothing;
             }
         }
     },
     q{
         static if (pred!(TList[0]))
         {
             static if (pred!(TList[1]))
             {
                 static if (pred!(TList[2]))
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[0], 
TList[1], TList[2], TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[0], 
TList[1], TList[2]);
                 }
                 else
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[0], 
TList[1], TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[0], 
TList[1]);
                 }
             }
             else
             {
                 static if (pred!(TList[2]))
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[0], 
TList[2], TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[0], 
TList[2]);
                 }
                 else
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[0], 
TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[0]);
                 }
             }
         }
         else
         {
             static if (pred!(TList[1]))
             {
                 static if (pred!(TList[2]))
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[1], 
TList[2], TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[1], 
TList[2]);
                 }
                 else
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[1], 
TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[1]);
                 }
             }
             else
             {
                 static if (pred!(TList[2]))
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[2], 
TList[3]);
                     else
                         alias Filter = AliasSeq!(TList[2]);
                 }
                 else
                 {
                     static if (pred!(TList[3]))
                         alias Filter = AliasSeq!(TList[3]);
                     else
                         alias Filter = Nothing;
                 }
             }
         }
     }
);

private enum filterExpandFactor = FilterShortCode.length;

package alias Nothing = AliasSeq!(); // yes, this really does 
speed up compilation!

---

--- actual 3 liner ---
    alias Numerics = AliasSeq!(byte, ubyte, short, ushort, int, 
uint, long,
             ulong, float, double, real, char, wchar, dchar);
         enum convertsTo(T, U) = is(T : U);
         alias ImplicitConversionTargets(T) = 
Filter!(ApplyLeft!(convertsTo, T), Numerics);
         pragma(msg, ImplicitConversionTargets!uint);
---

I would consider this illuminating in a way.


More information about the Digitalmars-d mailing list