Thread overview
constraint on variadic template
Dec 07, 2016
Alex
Dec 07, 2016
Adam D. Ruppe
Dec 07, 2016
Alex
Dec 07, 2016
H. S. Teoh
Dec 07, 2016
Alex
Dec 07, 2016
Adam D. Ruppe
Dec 07, 2016
Gary Willoughby
Dec 07, 2016
Alex
December 07, 2016
Hi people,
have searched the history, but didn't find something similar:

say I have a template like

mixin template S(T...)
{
    void run()
    {
        foreach(s; T)
        {
            static assert(__traits(hasMember, s, "run"));
        }
    }
}

How to formulate the check inside the foreach as a template constraint with
mixin template S(T...) if(???)

have tried so far:
mixin template S(T...) if(__traits(hasMember, T, "run"))
but the compiler complies about
Error: expected 2 arguments for hasMember but had 3
which says to me, that the input is not taken value by value, but all values as entirety.

tried:
if(T.each!(s => __traits(hasMember, s, "run")))
but it complies about
cannot deduce function from argument types !()(void, void)
which is ok, as the the provided types are templates by themselves.

The formulation at the beginning works, but the intention is a little bit different.

Thanks in advance
Alex
December 07, 2016
On Wednesday, 7 December 2016 at 16:35:52 UTC, Alex wrote:
>     void run()
>     {
>         foreach(s; T)
>         {
>             static assert(__traits(hasMember, s, "run"));
>         }
>     }

Just put that in a function:

bool test(T...)() {
   foreach(s; T)
      if(!__traits(hasMember, s, "run"))
          return false;
   return true;
}

and use that as the constraint:

S(T...) if (test!T()) {}
December 07, 2016
On Wednesday, 7 December 2016 at 16:48:08 UTC, Adam D. Ruppe wrote:
> On Wednesday, 7 December 2016 at 16:35:52 UTC, Alex wrote:
>>     void run()
>>     {
>>         foreach(s; T)
>>         {
>>             static assert(__traits(hasMember, s, "run"));
>>         }
>>     }
>
> Just put that in a function:
>
> bool test(T...)() {
>    foreach(s; T)
>       if(!__traits(hasMember, s, "run"))
>           return false;
>    return true;
> }
>
> and use that as the constraint:
>
> S(T...) if (test!T()) {}

Ah! An own constraint... Thanks! :)
December 07, 2016
On Wed, Dec 07, 2016 at 04:35:52PM +0000, Alex via Digitalmars-d-learn wrote:
> Hi people,
> have searched the history, but didn't find something similar:
> 
> say I have a template like
> 
> mixin template S(T...)
> {
>     void run()
>     {
>         foreach(s; T)
>         {
>             static assert(__traits(hasMember, s, "run"));
>         }
>     }
> }
> 
> How to formulate the check inside the foreach as a template constraint with
> mixin template S(T...) if(???)
[...]

Try this:

	import std.meta : allSatisfy;

	enum hasRun(T) = __traits(hasMember, T, "run");

	mixin template S(T...)
	    if (allSatisfy!(hasRun, T))
	{
	    void run()
	    {
		foreach(s; T)
		{
		    static assert(__traits(hasMember, s, "run"));
		}
	    }
	}


T

-- 
The richest man is not he who has the most, but he who needs the least.
December 07, 2016
On Wednesday, 7 December 2016 at 16:35:52 UTC, Alex wrote:
> mixin template S(T...)
> {
>     void run()
>     {
>         foreach(s; T)
>         {
>             static assert(__traits(hasMember, s, "run"));
>         }
>     }
> }
>
> How to formulate the check inside the foreach as a template constraint with
> mixin template S(T...) if(???)

Will some like this work?

    import std.range.primitives;

    mixin template S(T...) if(__traits(hasMember, ElementType!(T), "run"))
    {
        ...
    }

https://dlang.org/phobos/std_range_primitives.html#ElementType
December 07, 2016
On Wednesday, 7 December 2016 at 17:08:09 UTC, Gary Willoughby wrote:
>
> Will some like this work?
>
>     import std.range.primitives;
>
>     mixin template S(T...) if(__traits(hasMember, ElementType!(T), "run"))
>     {
>         ...
>     }
>
> https://dlang.org/phobos/std_range_primitives.html#ElementType

Nope:
template instance ElementType!(rFS, rAS) does not match template declaration ElementType(R)
December 07, 2016
On Wednesday, 7 December 2016 at 17:05:11 UTC, H. S. Teoh wrote:
> Try this:
>
> 	import std.meta : allSatisfy;
>
> 	enum hasRun(T) = __traits(hasMember, T, "run");
>
> 	mixin template S(T...)
> 	    if (allSatisfy!(hasRun, T))
> 	{
> 	    void run()
> 	    {
> 		foreach(s; T)
> 		{
> 		    static assert(__traits(hasMember, s, "run"));
> 		}
> 	    }
> 	}

This is strange... I expect this to work... but it does not...

meta.d(762,27): Error: template instance F!(rFS) does not match template declaration hasRun(T)
meta.d(767,13): Error: template instance std.meta.allSatisfy!(hasRun, rFS) error instantiating
test176.d(70,27): instantiated from here: allSatisfy!(hasRun, rFS, rAS)
December 07, 2016
On Wednesday, 7 December 2016 at 17:32:14 UTC, Alex wrote:
>> 	enum hasRun(T) = __traits(hasMember, T, "run");
> This is strange... I expect this to work... but it does not...
>

hasRun there ONLY takes types, whereas T... can take types, values, aliases, etc.

Try making it hasRun(T...) and it will probably work, though really, I'd say just use the helper function...