Thread overview
How do you call an eponymous template that has a secondary template arg?
Mar 11, 2018
aliak
Mar 11, 2018
Basile B.
Mar 11, 2018
aliak
Mar 12, 2018
Simen Kjærås
Mar 12, 2018
aliak
March 11, 2018
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

March 11, 2018
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"));
```
March 11, 2018
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.





March 12, 2018
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
March 12, 2018
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
}