www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do you call an eponymous template that has a secondary template

reply aliak <something something.com> writes:
Eg:

template aliasOf(T) {
     enum aliasOf(alias a) = is(typeof(a) == T);
}

The use case for this is for std.meta.allSatisfy for variadic 
args, i.e.

template T(values...) if (allSatisfy!(aliasOf!string, values) { 
... }

But how do you call that template otherwise?

I've tries:

* aliasOf!int!"string" // multiple ! arguments are not allowed
* (aliasOf!int)!"string" // error c-style cast
* aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
does not have property 'isAliasOf

I can work around this by:

template typeOf(T) {
     enum isAliasedBy(alias a) = is(typeof(a) == T);
}

and then do:

template T(values...) if (allSatisfy!(typeOf!string.isAliasedBy, 
values) { ... }

But I like the readability of the former better if there's a way 
to achieve it?

Cheers
- Ali
Mar 11 2018
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 11 March 2018 at 12:05:56 UTC, aliak wrote:
 Eg:

 template aliasOf(T) {
     enum aliasOf(alias a) = is(typeof(a) == T);
 }

 The use case for this is for std.meta.allSatisfy for variadic 
 args, i.e.

 template T(values...) if (allSatisfy!(aliasOf!string, values) { 
 ... }

 But how do you call that template otherwise?

 I've tries:

 * aliasOf!int!"string" // multiple ! arguments are not allowed
 * (aliasOf!int)!"string" // error c-style cast
 * aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
 does not have property 'isAliasOf

 I can work around this by:

 template typeOf(T) {
     enum isAliasedBy(alias a) = is(typeof(a) == T);
 }

 and then do:

 template T(values...) if 
 (allSatisfy!(typeOf!string.isAliasedBy, values) { ... }

 But I like the readability of the former better if there's a 
 way to achieve it?

 Cheers
 - Ali
The first version works here: ``` template aliasOf(T) { enum aliasOf(alias a) = is(typeof(a) == T); } string s; pragma(msg, allSatisfy!(aliasOf!string, s, "string")); ``` Now on the fact that what is done is correct is another story. If the literal passed is supposed to be a type then it's clearly wrong. You'd have to mix it: ``` template aliasOf(T) { template aliasOf(alias a) { mixin("alias A = " ~ a ~ ";"); enum aliasOf = is(A == T); } } alias myString1 = string; alias myString2 = string; pragma(msg, allSatisfy!(aliasOf!string, "myString1", "myString2")); ```
Mar 11 2018
parent aliak <something something.com> writes:
On Sunday, 11 March 2018 at 13:44:38 UTC, Basile B. wrote:
 The first version works here:

 ```
 template aliasOf(T) {
     enum aliasOf(alias a) = is(typeof(a) == T);
 }

 string s;

 pragma(msg, allSatisfy!(aliasOf!string, s, "string"));
 ```
I can see that my description was a little confusing, sorry about that, I meant to ask how would you call that without using the allSatisfy meta template. If I were to call it as a stand alone, ie: writeln(aliasOf!string<how do I pass argument to inner template?>); I hope that makes it clearer.
 Now on the fact that what is done is correct is another story.
 If the literal passed is supposed to be a type then it's 
 clearly wrong.
 You'd have to mix it:

 ```
 template aliasOf(T)
 {
     template aliasOf(alias a)
     {
         mixin("alias A = " ~ a ~ ";");
         enum aliasOf = is(A == T);
     }
 }

 alias myString1 = string;
 alias myString2 = string;

 pragma(msg, allSatisfy!(aliasOf!string, "myString1", 
 "myString2"));
 ```
Aye, I see what you mean, but it is supposed to be a literal of a specific type. I.e. 3, "some string", SomeType(), etc. So aliasOf!int.aliasOf!3 // true Also, if I define it like this: template aliasOf(T) { auto aliasOf(U)(U) { return is(U == T); } } Then at least I can call it like: writeln(aliasOf!int(3)); // prints true But then I can't do: allSatisfy!(aliasOf!int, 3) I guess because it's a function now and not a template anymore so can't be used by allSatisfy.
Mar 11 2018
prev sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Sunday, 11 March 2018 at 12:05:56 UTC, aliak wrote:
 * aliasOf!int!"string" // multiple ! arguments are not allowed
 * (aliasOf!int)!"string" // error c-style cast
 * aliasOf!int.aliasOf!"string" // template isAliasOf(alias a) 
 does not have property 'isAliasOf
Yeah, that's a little hole in the grammar, but there are ways: // Declare an alias: alias aliasOfInt = aliasOf!int; // And use that: assert(!aliasOfInt!string); Or use std.meta.Instantiate: assert(!Instantiate!(aliasOf!int, string)); -- Simen
Mar 11 2018
parent aliak <something something.com> writes:
On Monday, 12 March 2018 at 04:15:23 UTC, Simen Kjærås wrote:
 Yeah, that's a little hole in the grammar, but there are ways:

 // Declare an alias:
 alias aliasOfInt = aliasOf!int;

 // And use that:
 assert(!aliasOfInt!string);


 Or use std.meta.Instantiate:

 assert(!Instantiate!(aliasOf!int, string));

 --
   Simen
Noice! Did not know about instantiate. Btw: I just tried this and it worked, to my surprise!: template aliasOf(T) { auto aliasOf(U)(U) { return is(U == T); } enum aliasOf(alias a) = aliasOf!int(a); } void main() { writeln(aliasOf!int(3)); // works writeln(allSatisfy!(aliasOf!int, 3)); // works }
Mar 12 2018