Thread overview
Using allSatisfy with template that takes multiple type arguments
Sep 26, 2011
Andrej Mitrovic
Sep 26, 2011
David Nadlinger
Sep 27, 2011
Andrej Mitrovic
Sep 28, 2011
Christophe
Sep 28, 2011
bearophile
Sep 28, 2011
Andrej Mitrovic
September 26, 2011
import std.typetuple;
import std.traits;

alias TypeTuple!(int, float) MyTypes;
template isCompatible(T)
{
    enum bool isCompatible = allSatisfy!(isImplicitlyConvertible!T, MyTypes);
}

This won't work since the compiler tries to instantiate isImplicitlyConvertible with a single type (it takes two types).

The reason I'm doing this is to catch bad arguments inside of a static assert so I can give out better error messages and optionally provide a tip (based on a version switch). The above won't work, so do you know of a workaround?
September 26, 2011
On 9/26/11 9:32 PM, Andrej Mitrovic wrote:
> alias TypeTuple!(int, float) MyTypes;
> template isCompatible(T)
> {
>      enum bool isCompatible = allSatisfy!(isImplicitlyConvertible!T, MyTypes);
> }

template PApply(alias Target, T...) {
  template PApply(U...) {
    alias Target!(T, U) PApply;
  }
}

…

enum isCompatible = allSatisfy!(PApply!(isImplicitlyConvertible, T), MyTypes);

David
September 27, 2011
Thanks for the tips guys. I have another similar issue now, I want to check whether a type passes any of the predicates I list. This would be similar to anySatisfy, however anySatisfy takes one predicate and multiple types, and what I need is one type and multiple predicates, e.g.:

anyPredicateSatisfy!(int, isNumeric, isIntegral);

I've tried copying anySatisfy's code and modifying it to work:

template anyPredicateSatisfy(T, F...)
{
    static if (F.length == 0)
    {
        enum bool anySatisfy = false;
    }
    else static if (F.length == 1)
    {
        enum bool anySatisfy = (F[0])!T;
    }
    else
    {
        enum bool anySatisfy = (F[0])!T) || anySatisfy!(T, F[1 .. $]);
    }
}

But the compiler thinks I'm doing C-style casts so this doesn't work. Any clues?
September 28, 2011
Andrej Mitrovic , dans le message (digitalmars.D.learn:29825), a écrit :
> Thanks for the tips guys. I have another similar issue now, I want to check whether a type passes any of the predicates I list. This would be similar to anySatisfy, however anySatisfy takes one predicate and multiple types, and what I need is one type and multiple predicates, e.g.:
> 
> anyPredicateSatisfy!(int, isNumeric, isIntegral);
> 
> I've tried copying anySatisfy's code and modifying it to work:
> 
> template anyPredicateSatisfy(T, F...)
> {
>     static if (F.length == 0)
>     {
>         enum bool anySatisfy = false;
>     }
>     else static if (F.length == 1)
>     {
>         enum bool anySatisfy = (F[0])!T;
>     }
>     else
>     {
>         enum bool anySatisfy = (F[0])!T) || anySatisfy!(T, F[1 .. $]);
                                              ^ you mean anyPredicateSatisfy
>     }
> }
> 
> But the compiler thinks I'm doing C-style casts so this doesn't work. Any clues?

September 28, 2011
Andrej Mitrovic:

> But the compiler thinks I'm doing C-style casts so this doesn't work. Any clues?

This seems to work (eye the base of the recursion):

template satisfies(T, alias P) { enum satisfies = P!T; }

template anyPredicateSatisfy(T, Preds...) {
    static if (Preds.length)
        //enum bool anyPredicateSatisfy = (Preds[0]!T) || anyPredicateSatisfy!(T, Preds[1 .. $]);
        enum bool anyPredicateSatisfy = satisfies!(T, Preds[0]) || anyPredicateSatisfy!(T, Preds[1 .. $]);
    else
        enum bool anyPredicateSatisfy = false;
}

template is4(T) { enum is4 = T.sizeof == 4; }
template signed(T) { enum signed = T.min != 0; }

static assert(anyPredicateSatisfy!(int, is4, signed));

void main() {}


Maybe the error on (Preds[0]!T) is fodder for Bugzilla.

Bye,
bearophile
September 28, 2011
Thanks, that works. I'll report the bug as well.