Jump to page: 1 2
Thread overview
Sequence separation
Aug 16, 2016
Engine Machine
Aug 16, 2016
Adam D. Ruppe
Aug 17, 2016
Lodovico Giaretta
Aug 17, 2016
Engine Machine
Aug 17, 2016
ag0aep6g
Aug 17, 2016
Lodovico Giaretta
Aug 17, 2016
Engine Machine
Aug 17, 2016
ag0aep6g
Aug 17, 2016
Engine Machine
Aug 21, 2016
Alexandru Ermicioi
Aug 17, 2016
Engine Machine
August 16, 2016
alias x = AliasSeq!(a, b, AliasSeq!(c, d));

results in a flat sequence. I would like to be able to keep them separate so I can have sub sequences.

x.length == 4;


August 16, 2016
On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine wrote:
> alias x = AliasSeq!(a, b, AliasSeq!(c, d));
>
> results in a flat sequence. I would like to be able to keep them separate so I can have sub sequences.

wrap them in a struct.
August 17, 2016
On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
> On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine wrote:
>> alias x = AliasSeq!(a, b, AliasSeq!(c, d));
>>
>> results in a flat sequence. I would like to be able to keep them separate so I can have sub sequences.
>
> wrap them in a struct.

You mean something like:

struct MySequence(Args...)
{
    enum length = Args.length;
    alias args = Args;
}

alias x = MySequence!(a, b, MySequence!(c, d));

static assert(x.length == 3)
static assert(x.args[2].length == 2);
August 17, 2016
On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote:
> On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
>> On Tuesday, 16 August 2016 at 19:17:27 UTC, Engine Machine wrote:
>>> alias x = AliasSeq!(a, b, AliasSeq!(c, d));
>>>
>>> results in a flat sequence. I would like to be able to keep them separate so I can have sub sequences.
>>
>> wrap them in a struct.
>
> You mean something like:
>
> struct MySequence(Args...)
> {
>     enum length = Args.length;
>     alias args = Args;
> }
>
> alias x = MySequence!(a, b, MySequence!(c, d));
>
> static assert(x.length == 3)
> static assert(x.args[2].length == 2);

Thanks, basically works.

How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe.

I could do some string tests, but that doesn't work.

in your exmaple,

if (x.args[2] == MySequence) ??

I simply need to differentiate between a parameter/arg being a MySequence and not.



August 17, 2016
On 08/17/2016 08:38 PM, Engine Machine wrote:
> On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote:
[...]
>> You mean something like:
>>
>> struct MySequence(Args...)
>> {
>>     enum length = Args.length;
>>     alias args = Args;
>> }
>>
>> alias x = MySequence!(a, b, MySequence!(c, d));
>>
>> static assert(x.length == 3)
>> static assert(x.args[2].length == 2);
>
> Thanks, basically works.
>
> How can I test, though, if a argument uses a MySequence? I can't do if
> (Args[0] == MySequence) because MySequence is templated. While I could
> test for a length, that doesn't work because some types have a length. I
> could add another enum to MySequence, but again, not safe.
>
> I could do some string tests, but that doesn't work.
>
> in your exmaple,
>
> if (x.args[2] == MySequence) ??
>
> I simply need to differentiate between a parameter/arg being a
> MySequence and not.

With MySequence being a type, you can do this:

----
static if (is(x.args[2] == MySequence!Args, Args ...))
{
  ...
}
----

Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence.

As you said, another enum alone doesn't cut it. The faker can just add the same enum.

But a private enum of a private type might do it:

----
template MySequence(Args ...)
{
    /* ... length and args ... */
    private enum id = Id();
}

private struct Id {}

enum isMySequence(alias seq) =  is(typeof(seq.id) == Id);
----

Other modules can't use the Id type directly, because it's private. And they can't use typeof(MySequence!foo.id), because the id member is private, too.

However, I wouldn't be surprised if this can be circumvented too.
August 17, 2016
On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:
> On 08/17/2016 08:38 PM, Engine Machine wrote:
>> On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote:
> [...]
>>> You mean something like:
>>>
>>> struct MySequence(Args...)
>>> {
>>>     enum length = Args.length;
>>>     alias args = Args;
>>> }
>>>
>>> alias x = MySequence!(a, b, MySequence!(c, d));
>>>
>>> static assert(x.length == 3)
>>> static assert(x.args[2].length == 2);
>>
>> Thanks, basically works.
>>
>> How can I test, though, if a argument uses a MySequence? I can't do if
>> (Args[0] == MySequence) because MySequence is templated. While I could
>> test for a length, that doesn't work because some types have a length. I
>> could add another enum to MySequence, but again, not safe.
>>
>> I could do some string tests, but that doesn't work.
>>
>> in your exmaple,
>>
>> if (x.args[2] == MySequence) ??
>>
>> I simply need to differentiate between a parameter/arg being a
>> MySequence and not.
>
> With MySequence being a type, you can do this:
>
> ----
> static if (is(x.args[2] == MySequence!Args, Args ...))
> {
>   ...
> }
> ----
>
> Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence.

import std.traits: TemplateOf;
static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence))
{
    ...
}

std.traits.TemplateOf extracts the symbol representing the uninstantiated template.

__traits(isSame, symbol1, symbol2) evaluates at compile time to true if and only if the two symbols represent the same thing (be it a type, an uninstantiated template, an instantiated one or whatever else).
August 17, 2016
On Wednesday, 17 August 2016 at 18:38:48 UTC, Engine Machine wrote:
> On Wednesday, 17 August 2016 at 08:37:32 UTC, Lodovico Giaretta wrote:
>> On Tuesday, 16 August 2016 at 23:18:28 UTC, Adam D. Ruppe wrote:
>>> [...]
>>
>> You mean something like:
>>
>> struct MySequence(Args...)
>> {
>>     enum length = Args.length;
>>     alias args = Args;
>> }
>>
>> alias x = MySequence!(a, b, MySequence!(c, d));
>>
>> static assert(x.length == 3)
>> static assert(x.args[2].length == 2);
>
> Thanks, basically works.
>
> How can I test, though, if a argument uses a MySequence? I can't do if (Args[0] == MySequence) because MySequence is templated. While I could test for a length, that doesn't work because some types have a length. I could add another enum to MySequence, but again, not safe.
>
> I could do some string tests, but that doesn't work.
>
> in your exmaple,
>
> if (x.args[2] == MySequence) ??
>
> I simply need to differentiate between a parameter/arg being a MySequence and not.

I guess I'll go with something like

static if ((a.Args[2]).stringof[0..11] == "MySequence!")

Doesn't feel entirely safe but probably will work without issue.

Maybe there is a better way?
August 17, 2016
On Wednesday, 17 August 2016 at 19:21:57 UTC, Lodovico Giaretta wrote:
> On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:

>> [...]
>
> import std.traits: TemplateOf;
> static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence))
> {
>     ...
> }
>
> std.traits.TemplateOf extracts the symbol representing the uninstantiated template.
>
> __traits(isSame, symbol1, symbol2) evaluates at compile time to true if and only if the two symbols represent the same thing (be it a type, an uninstantiated template, an instantiated one or whatever else).

Thanks!

To note, it error's if there is no match ;/
August 17, 2016
On Wednesday, 17 August 2016 at 19:15:48 UTC, ag0aep6g wrote:
> On 08/17/2016 08:38 PM, Engine Machine wrote:
>> [...]
> [...]
>> [...]
>
> With MySequence being a type, you can do this:
>
> ----
> static if (is(x.args[2] == MySequence!Args, Args ...))
> {
>   ...
> }
> ----
>
It works! Nifty that you can do that with is.

> Aside from this check, there is probably not much use for MySequence being a type. So I'm be tempted to find a way to do the check with a raw template MySequence.
>
> As you said, another enum alone doesn't cut it. The faker can just add the same enum.
>
> But a private enum of a private type might do it:
>
> ----
> template MySequence(Args ...)
> {
>     /* ... length and args ... */
>     private enum id = Id();
> }
>
> private struct Id {}
>
> enum isMySequence(alias seq) =  is(typeof(seq.id) == Id);
> ----
>
> Other modules can't use the Id type directly, because it's private. And they can't use typeof(MySequence!foo.id), because the id member is private, too.
>
> However, I wouldn't be surprised if this can be circumvented too.

Well, the is does work and that probably is the best solution. I don't mind the extra type at this point. Of course, a library solution for this type of stuff would be nice. I'd rather not have to even use a type but rather use arrays:
[a,b,[c,d]].

August 17, 2016
On 08/17/2016 09:21 PM, Lodovico Giaretta wrote:
> import std.traits: TemplateOf;
> static if (__traits(isSame, TemplateOf!(x.args[2]), MySequence))
> {
>     ...
> }
>
> std.traits.TemplateOf extracts the symbol representing the
> uninstantiated template.
>
> __traits(isSame, symbol1, symbol2) evaluates at compile time to true if
> and only if the two symbols represent the same thing (be it a type, an
> uninstantiated template, an instantiated one or whatever else).

Look at that! Much better.

TemplateOf is implemented with a template specialization, which can handle other things than types, unlike `is(...)`.

Using that directly, without going to std.traits, isMySequence could be done like this:

----
enum isMySequence(alias thing : MySequence!args, args ...) = true;
enum isMySequence(alias thing) = false;
----

That's just me toying around with the language, of course. The isSame+TemplateOf version is perfectly fine.
« First   ‹ Prev
1 2