Jump to page: 1 2
Thread overview
Checking that a template parameter is an enum
Oct 01, 2015
Nordlöw
Oct 01, 2015
Fusxfaranto
Oct 01, 2015
Nordlöw
Oct 01, 2015
Nordlöw
Oct 01, 2015
Ali Çehreli
Oct 01, 2015
Nordlöw
Oct 02, 2015
Meta
Oct 02, 2015
Nordlöw
Oct 02, 2015
Meta
Oct 02, 2015
Nordlöw
Oct 02, 2015
Meta
Oct 02, 2015
Per Nordlöw
Oct 02, 2015
John Colvin
Oct 02, 2015
John Colvin
October 01, 2015
How do I check that a template parameter is a CT-value or an enum symbol?

I want this to restrict the following template:

/** Returns: true iff all values $(D V) are the same. */
template allSame(V...)          // TODO restrict to values only
{
    static if (V.length <= 1)
        enum bool allSame = true;
    else
        enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
}

unittest
{
    static assert(!allSame!(41, 42));
    static assert(allSame!(42, 42, 42));
}

October 01, 2015
On Thursday, 1 October 2015 at 00:04:18 UTC, Nordlöw wrote:
> How do I check that a template parameter is a CT-value or an enum symbol?
>
> I want this to restrict the following template:
>
> /** Returns: true iff all values $(D V) are the same. */
> template allSame(V...)          // TODO restrict to values only
> {
>     static if (V.length <= 1)
>         enum bool allSame = true;
>     else
>         enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
> }
>
> unittest
> {
>     static assert(!allSame!(41, 42));
>     static assert(allSame!(42, 42, 42));
> }

std.traits to the rescue!

http://dlang.org/phobos/std_traits.html#isExpressions

Using isExpressions!V as a template constraint looks like the behavior you're looking for.
October 01, 2015
On Thursday, 1 October 2015 at 02:06:48 UTC, Fusxfaranto wrote:
>> /** Returns: true iff all values $(D V) are the same. */
>> template allSame(V...)          // TODO restrict to values only
>> {
>>     static if (V.length <= 1)
>>         enum bool allSame = true;
>>     else
>>         enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
>> }
>
> std.traits to the rescue!
>
> http://dlang.org/phobos/std_traits.html#isExpressions
>
> Using isExpressions!V as a template constraint looks like the behavior you're looking for.

Thanks!

BTW: Is there some way to turn the recursive definition of `allSame` into an iterative definition?
October 01, 2015
On Thursday, 1 October 2015 at 02:06:48 UTC, Fusxfaranto wrote:
>> /** Returns: true iff all values $(D V) are the same. */
>> template allSame(V...)          // TODO restrict to values only
>> {
>>     static if (V.length <= 1)
>>         enum bool allSame = true;
>>     else
>>         enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
>> }
>
> std.traits to the rescue!
>
> http://dlang.org/phobos/std_traits.html#isExpressions
>
> Using isExpressions!V as a template constraint looks like the behavior you're looking for.

Thanks!

BTW: Is there some way to turn the recursive definition of `allSame`

template allSame(V...)
    if (isExpressions!(V))
{
    static if (V.length <= 1)
        enum allSame = true;
    else
        enum allSame = V[0] == V[1] && allSame!(V[1..$]);
}

into an iterative definition?
October 01, 2015
On 10/01/2015 03:26 PM, Nordlöw wrote:
> On Thursday, 1 October 2015 at 02:06:48 UTC, Fusxfaranto wrote:
>>> /** Returns: true iff all values $(D V) are the same. */
>>> template allSame(V...)          // TODO restrict to values only
>>> {
>>>     static if (V.length <= 1)
>>>         enum bool allSame = true;
>>>     else
>>>         enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
>>> }
>>
>> std.traits to the rescue!
>>
>> http://dlang.org/phobos/std_traits.html#isExpressions
>>
>> Using isExpressions!V as a template constraint looks like the behavior
>> you're looking for.
>
> Thanks!
>
> BTW: Is there some way to turn the recursive definition of `allSame`
>
> template allSame(V...)
>      if (isExpressions!(V))
> {
>      static if (V.length <= 1)
>          enum allSame = true;
>      else
>          enum allSame = V[0] == V[1] && allSame!(V[1..$]);
> }
>
> into an iterative definition?

Very quickly:

import std.traits;

template allSame(V...)
    if (isExpressions!(V))
{
    bool impl_(V...)() {
        static if (V.length > 1) {
            foreach (i, _; V[0 .. $ - 1]) {
                if (V[i] != V[i + 1]) {
                    return false;
                }
            }

            return true;

        } else {
            return true;
        }
    }

    enum allSame = impl_!V();
}

unittest
{
    static assert( allSame!());
    static assert( allSame!(42));
    static assert( allSame!(42, 42, 42));
    static assert(!allSame!(42, 43, 42));
}

Ali

October 01, 2015
On Thursday, 1 October 2015 at 22:37:57 UTC, Ali Çehreli wrote:
> Very quickly:
>
> import std.traits;
>
> template allSame(V...)
>     if (isExpressions!(V))
> {
>     bool impl_(V...)() {
>         static if (V.length > 1) {
>             foreach (i, _; V[0 .. $ - 1]) {
>                 if (V[i] != V[i + 1]) {
>                     return false;
>                 }
>             }
>
>             return true;
>
>         } else {
>             return true;
>         }
>     }
>
>     enum allSame = impl_!V();
> }

Will this spare memory in DMD? If so there are a few traits that should be update accordingly, for instance `allSatisfy` and `anySatisfy`.

Thanks!
October 02, 2015
On Thursday, 1 October 2015 at 22:41:21 UTC, Nordlöw wrote:
> Will this spare memory in DMD? If so there are a few traits that should be update accordingly, for instance `allSatisfy` and `anySatisfy`.
>
> Thanks!

Highly doubtful as CTFE already allocates like there's no tomorrow.
October 02, 2015
On Friday, 2 October 2015 at 02:39:56 UTC, Meta wrote:
> Highly doubtful as CTFE already allocates like there's no tomorrow.

Could that memory usage be tested somehow?
October 02, 2015
On Thursday, 1 October 2015 at 22:26:39 UTC, Nordlöw wrote:
> On Thursday, 1 October 2015 at 02:06:48 UTC, Fusxfaranto wrote:
>>> /** Returns: true iff all values $(D V) are the same. */
>>> template allSame(V...)          // TODO restrict to values only
>>> {
>>>     static if (V.length <= 1)
>>>         enum bool allSame = true;
>>>     else
>>>         enum bool allSame = V[0] == V[1] && allSame!(V[1..$]);
>>> }
>>
>> std.traits to the rescue!
>>
>> http://dlang.org/phobos/std_traits.html#isExpressions
>>
>> Using isExpressions!V as a template constraint looks like the behavior you're looking for.
>
> Thanks!
>
> BTW: Is there some way to turn the recursive definition of `allSame`
>
> template allSame(V...)
>     if (isExpressions!(V))
> {
>     static if (V.length <= 1)
>         enum allSame = true;
>     else
>         enum allSame = V[0] == V[1] && allSame!(V[1..$]);
> }
>
> into an iterative definition?

Why? To avoid slowing down compilation with all those template instantiations?

How about a O(log2(N)) depth recursive version, something like this:

template allSame(V ...)
    if (isExpressions!V)
{
    static if (V.length <= 1)
        enum allSame = true;
    else static if(V.length & 1)
        enum allSame = V[$-1] == V[0]
            && V[0 .. $/2] == V[$/2 .. $-1]
            && allSame!(V[0 .. $/2]);
    else
        enum allSame = V[0..$/2] == V[$/2 .. $]
            && allSame!(V[0 .. $/2]);
}
October 02, 2015
On Friday, 2 October 2015 at 08:13:00 UTC, John Colvin wrote:
> On Thursday, 1 October 2015 at 22:26:39 UTC, Nordlöw wrote:
>> On Thursday, 1 October 2015 at 02:06:48 UTC, Fusxfaranto wrote:
>>> [...]
>>
>> Thanks!
>>
>> BTW: Is there some way to turn the recursive definition of `allSame`
>>
>> template allSame(V...)
>>     if (isExpressions!(V))
>> {
>>     static if (V.length <= 1)
>>         enum allSame = true;
>>     else
>>         enum allSame = V[0] == V[1] && allSame!(V[1..$]);
>> }
>>
>> into an iterative definition?
>
> Why? To avoid slowing down compilation with all those template instantiations?
>
> How about a O(log2(N)) depth recursive version, something like this:
>
> template allSame(V ...)
>     if (isExpressions!V)
> {
>     static if (V.length <= 1)
>         enum allSame = true;
>     else static if(V.length & 1)
>         enum allSame = V[$-1] == V[0]
>             && V[0 .. $/2] == V[$/2 .. $-1]
>             && allSame!(V[0 .. $/2]);
>     else
>         enum allSame = V[0..$/2] == V[$/2 .. $]
>             && allSame!(V[0 .. $/2]);
> }

Although you should consider that isExpressions is instantiating V.length templates anyway (it uses a binary split to avoid excessive template recursion depth, but it ends up checking them all one-per-template in the end anyway.
« First   ‹ Prev
1 2