D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6573 - Add isOneOf to std.traits
Summary: Add isOneOf to std.traits
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: Other Windows
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-08-29 19:15 UTC by Andrej Mitrovic
Modified: 2016-08-27 22:21 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2011-08-29 19:15:23 UTC
I think Steven Schveighoffer came up with this originally:

template isOneOf(X, T...)
{
    static if (!T.length)
        enum bool isOneOf = false;
    else static if (is (X == T[0]))
        enum bool isOneOf = true;
    else
        enum bool isOneOf = isOneOf!(X, T[1..$]);
}

It's very useful as a replacement for multiple checks on a single type parameter, e.g.:

void foo(T)(T t) if (is(T == Type1) || is(T == Type2) || is(T == Type3))

turns into:

void foo(T)(T t) if (isOneOf!(T, Type1, Type2, Type3))
Comment 1 Andrej Mitrovic 2011-08-29 20:16:51 UTC
However the code will have to be slightly improved.

If you accidentally pass a tuple followed by a single type things can get weird.

E.g.:

template isOneOf(X, T...)
{
    static if (!T.length)
        enum bool isOneOf = false;
    else static if (is (X == T[0]))
        enum bool isOneOf = true;
    else
        enum bool isOneOf = isOneOf!(X, T[1..$]);
}

void test(T...)(T t)
{
    static assert (isOneOf!(T, double));  // passes by mistake
    static assert (isOneOf!(double, T));  // ok, fails properly

}

void main()
{
    test(1, 2, 3);
}

So that's something to improve.
Comment 2 bearophile_hugs 2011-08-30 01:51:23 UTC
Something like this? (A different recursion base):


template SameTypes(X, T...) {
    static if (T.length)
        enum bool SameTypes = is(X == T[0]) && SameTypes!(X, T[1 .. $]);
    else
        enum bool SameTypes = true;
}


void main() {
    static assert (!SameTypes!(int, int, int, double));
    static assert (!SameTypes!(double, int, int, int));
    static assert (SameTypes!(double));
    static assert (SameTypes!(int));
    static assert (SameTypes!(int, typeof(1)));
    static assert (SameTypes!(int, typeof(1), typeof(2)));
}
Comment 3 kennytm 2011-08-30 04:39:01 UTC
I think this should be in std.typetuple, and also can be implemented using anySatisfy.

    template isOneOf(X, T...) {
       enum isOneOf = anySatisfy!(staticEqualsTo!X, T);
    }

    private template staticEqualsTo(X) {
       template staticEqualsTo(Y) {
          enum staticEqualsTo = isSame!(X, Y);
          // ^ isSame is a private template in std.typetuple.
       }
    }
Comment 4 Peter Alexander 2014-01-26 09:19:55 UTC
You can also use staticIndexOf

template isOneOf(X, T...)
{
    enum isOneOf = staticIndexOf(X, TypeTuple!T) != -1;
}
Comment 5 Andrej Mitrovic 2014-01-26 11:53:05 UTC
(In reply to comment #4)
> You can also use staticIndexOf
> 
> template isOneOf(X, T...)
> {
>     enum isOneOf = staticIndexOf(X, TypeTuple!T) != -1;
> }

Unfortunately staticIndexOf slows down compilation on more demanding template metaprogramming:

http://forum.dlang.org/thread/mailman.1418.1346015010.31962.digitalmars-d@puremagic.com
Comment 6 Andrej Mitrovic 2016-08-27 22:21:38 UTC
We have anySatisfy for this now:

-----
import std.meta;

void main()
{
    enum isInt ( T ) = is(T == int);
    static assert(anySatisfy!(isInt, float, char, int));
    static assert(!anySatisfy!(isInt, float, char));
}
-----