www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Checking that a template parameter is an enum

reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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));
}
Sep 30 2015
parent reply Fusxfaranto <fusxfaranto gmail.com> writes:
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.
Sep 30 2015
next sibling parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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?
Oct 01 2015
prev sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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?
Oct 01 2015
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Oct 01 2015
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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!
Oct 01 2015
parent reply Meta <jared771 gmail.com> writes:
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.
Oct 01 2015
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
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?
Oct 02 2015
parent reply Meta <jared771 gmail.com> writes:
On Friday, 2 October 2015 at 07:52:22 UTC, Nordlöw wrote:
 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?
Your favourite process monitor I guess.
Oct 02 2015
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Friday, 2 October 2015 at 16:21:22 UTC, Meta wrote:
 Could that memory usage be tested somehow?
Your favourite process monitor I guess.
Any suggestions on an evil D snippet that stress tests different implementations of the above mentioned traits?
Oct 02 2015
parent Meta <jared771 gmail.com> writes:
On Friday, 2 October 2015 at 18:52:22 UTC, Nordlöw wrote:
 On Friday, 2 October 2015 at 16:21:22 UTC, Meta wrote:
 Could that memory usage be tested somehow?
Your favourite process monitor I guess.
Any suggestions on an evil D snippet that stress tests different implementations of the above mentioned traits?
I don't know off the top of my head, but I remember somebody on these forums mentioning a certain CTFE program that caused DMD to take up over 100GB in RAM before the process was killed.
Oct 02 2015
prev sibling parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 1 October 2015 at 22:37:57 UTC, Ali Çehreli wrote:
 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 proposed `static foreach` reduce number of instantiations here?
Oct 02 2015
prev sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
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]); }
Oct 02 2015
parent John Colvin <john.loughran.colvin gmail.com> writes:
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.
Oct 02 2015