Thread overview
How to enumerate a sequence?
Feb 27, 2019
Victor Porton
Feb 27, 2019
Victor Porton
Feb 27, 2019
Simen Kjærås
February 27, 2019
.enumerate does not work for compile-time sequences. Consider for the sake of discussion the following nonsense (I know it cannot be done without enumerate) code:

import std.meta;
import std.range;

string join(Fields...)() {
  enum f(size_t i) = __traits(identifier, Fields[i]);
  return staticMap!f(Fields.enumerate).join('\n'); // does not compile because of .enumerate
}

void main(string[] args)
{
    string r = join!(int, float)();
}

How to make it compile?
February 27, 2019
On Wednesday, 27 February 2019 at 13:15:06 UTC, Victor Porton wrote:
> .enumerate does not work for compile-time sequences. Consider for the sake of discussion the following nonsense (I know it cannot be done without enumerate) code:

I want namely integer (or size_t) index!
February 27, 2019
On Wednesday, 27 February 2019 at 13:15:06 UTC, Victor Porton wrote:
> .enumerate does not work for compile-time sequences. Consider for the sake of discussion the following nonsense (I know it cannot be done without enumerate) code:
>
> import std.meta;
> import std.range;
>
> string join(Fields...)() {
>   enum f(size_t i) = __traits(identifier, Fields[i]);
>   return staticMap!f(Fields.enumerate).join('\n'); // does not compile because of .enumerate
> }
>
> void main(string[] args)
> {
>     string r = join!(int, float)();
> }
>
> How to make it compile?

Sadly, we cannot treat all compile-time values the same way we do run-time values. In this case, that's evident with Fields being an AliasSeq, not an array or other range. Since enumerate and join operate on ranges, they get confused when you give them an AliasSeq.

You also are probably not giving enough information about what you're actually trying to do. First, __traits(identifier, Fields[0]) simply fails to compile with the given arguments, since int doesn't have an identifier. Second, it's very unclear why you need an int index, since you're not using it in a way you couldn't easier do without. Here's how I would implement your join function wihout any further knowledge of these questions:

// Moved outside join due to the thrice-damned issue 5710
enum getIdentifier(T...) = __traits(identifier, T[0]);
string join(Fields...)() {
    import std.range : join;
    import std.meta : staticMap;

    alias names = staticMap!(getIdentifier, Fields);
    return [names].join('\n');
}

However, since you seem adamant you need the index as an int or size_t:

string join(Fields...)() {
    import std.range : join, iota;
    import std.meta : staticMap, aliasSeqOf;

    enum getIdentifier(size_t i) = __traits(identifier, Fields[i]);

    alias numbers = aliasSeqOf!(Fields.length.iota);
    return [staticMap!(getIdentifier, numbers)].join('\n');
}

Also, fixed the calling code so it has actual identifiers:

void main(string[] args)
{
    int i;
    float f;
    string r = join!(i, f)();
}

--
  Simen