www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - constraint on variadic template

reply Alex <sascha.orlov gmail.com> writes:
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
Dec 07 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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()) {}
Dec 07 2016
parent Alex <sascha.orlov gmail.com> writes:
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! :)
Dec 07 2016
prev sibling next sibling parent reply Gary Willoughby <dev nomad.so> writes:
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
Dec 07 2016
parent Alex <sascha.orlov gmail.com> writes:
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)
Dec 07 2016
prev sibling parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
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.
Dec 07 2016
parent reply Alex <sascha.orlov gmail.com> writes:
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)
Dec 07 2016
parent Adam D. Ruppe <destructionator gmail.com> writes:
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...
Dec 07 2016