The following code inserts properties for each type,
auto name = "Value"~((i == 0) ? "" : to!string(i++));
always as the i == 0 evaluate to true.
My question is, why the heck is it so hard to use basic
programming structs inside CTFE's? I know that CTFE's have to
work at run time also, so there is a limitation, but:
1. obviously ints work because the code below works with i as a
counter but we can't do a simple compare on it... this seems like
a bug.
2. foreach can be used but a simple for loop can't... makes no
sense.
I know what the average response is going to be but hopefully
someone will surprise me with some useful.
mixin template PropertyBuilder(T...)
{
template _(TT...)
{
static string eval()
{
string s;
pragma(msg, TT);
int i = 0;
foreach(t; TT)
{
auto name = "Value"~((i > 0) ? "" : to!string(i++));
s = " property "~t.stringof~" "~name~"();\n";
s ~=" property "~t.stringof~" "~name~"("~t.stringof~"
value);\n";
}
return s;
}
enum _ = eval();
pragma(msg, _);
}
mixin("mixin(_!T);");
}
interface a(MT...)
{
mixin PropertyBuilder!MT;
}

The following code inserts properties for each type,
auto name = "Value"~((i == 0) ? "" : to!string(i++));
always as the i == 0 evaluate to true.
1. obviously ints work because the code below works with i as a
counter but we can't do a simple compare on it... this seems
like a bug.

this is a mistake, I'm not sure what's going on, i seems to
increment but name always seems to evaluate to the largest i.

The following code inserts properties for each type,
auto name = "Value"~((i == 0) ? "" : to!string(i++));
always as the i == 0 evaluate to true.
1. obviously ints work because the code below works with i as
a counter but we can't do a simple compare on it... this seems
like a bug.

this is a mistake, I'm not sure what's going on, i seems to
increment but name always seems to evaluate to the largest i.

sheit... sorry, stupid mistake..
the issue with the foreach is still under question though, when I
try to use a for loop with i and access TT[i] I get an error
about i not being compile time readable. (maybe this is because
of how the type tuple is defined? possibly need a index method to
get the value?)

the issue with the foreach is still under question though, when
I try to use a for loop with i and access TT[i] I get an error
about i not being compile time readable. (maybe this is because
of how the type tuple is defined? possibly need a index method
to get the value?)

Because i is not a compile-time value, it is a normal variable.
And TT is a type tuple, pure compile-time entity. You really need
to study the documentation on this topic or frustration will
continue.

the issue with the foreach is still under question though,
when I try to use a for loop with i and access TT[i] I get an
error about i not being compile time readable. (maybe this is
because of how the type tuple is defined? possibly need a
index method to get the value?)

Because i is not a compile-time value, it is a normal variable.
And TT is a type tuple, pure compile-time entity. You really
need to study the documentation on this topic or frustration
will continue.

This has nothing to do with it...
string name = "Value"~((i==0) ? "" : (to!string(i)));
i++;
works, but
string name = "Value"~((i==0) ? "" : (to!string(i++)));
but doesn't....
It is a matter of placement of the increment operation on i that
is breaking the code and has nothing to do with your default
answer of "you don't know how CTFE's work, read the docs!" and
"... it's not a compile-time variable".
If i's not possible to use at compile time then none of the
following code examples should work
One could argue that depending on how to!string works could be
the issue, but this has nothing to do with i, which is what you
have stated, but to!string.
If it is to!string or templates in general that are the issue
then it is confusing to have the same syntax for compile time and
runtime but some common runtime syntax doesn't work.
e.g.,
int x = 0;
writeln(x);
to!string(x++);
writeln(x);
works fine at run-time, but to!string(i++) fails and
to!string(i); i++; works in CTFE...
So, either this is what you were getting at but didn't explain it
well(making the issue about i when it is about CTFE templates) or
you didn't understand the issue yourself.
int i = 0;
foreach(t; T)
{
string name = "Value"~((i==0) ? "" : (to!string(i)));
i++;
}
vs
int i = 0;
foreach(t; T)
{
string name = "Value"~((i==0) ? "" : (to!string(i++)));
}
vs
foreach(i, t; T)
{
string name = "Value"~((i==0) ? "" : (to!string(i)));
}
all are suppose to do the same thing and are all essentially
semantically identical... they should do the same. (at least
according to your logic and the compiler error message that says
the issue is with i)

Ultimately, the point is, that I thought CTFE's were suppose to
be compile time runnable functions. The problem is, the actual
language grammar changes. can use i++ as an argument to a
template at runtime without issue but not at compile time... and
since this seems to be the case from the examples I've posted,
this causes, at least for me, a lot of confusion. (who knows what
other differences there are) (and IMO they are flaws in the CTFE
system... although maybe there is some deep underlying reason why
it must be done that way)

Ultimately, the point is, that I thought CTFE's were suppose to
be compile time runnable functions. The problem is, the actual
language grammar changes. can use i++ as an argument to a
template at runtime without issue but not at compile time... and
since this seems to be the case from the examples I've posted,
this causes, at least for me, a lot of confusion. (who knows what
other differences there are) (and IMO they are flaws in the CTFE
system... although maybe there is some deep underlying reason why
it must be done that way)

If you look through the thread, others said that the behavoir
is the same in C at runtime. Your use of the ternary operator
is the problem. Only the branch that is taken is executed.
This should be obvious, but I agree that when the other branch
contains an i++ it looks like it should be executed. Please
look at the ternary operator as an if and else and it will
become clear why your increment works when you put it on a
separate line.
TL;DR: It has nothing to do with flaws in D or CTFE. At least
not this time around. ;)
--
Marco

the issue with the foreach is still under question though, when I try to use a
for loop with i and access TT[i] I get an error about i not being compile time
readable. (maybe this is because of how the type tuple is defined? possibly
need a index method to get the value?)

Because i is not a compile-time value, it is a normal variable. And TT is a
type tuple, pure compile-time entity. You really need to study the
documentation on this topic or frustration will continue.

This has nothing to do with it...
string name = "Value"~((i==0) ? "" : (to!string(i)));
i++;
works, but
string name = "Value"~((i==0) ? "" : (to!string(i++)));
but doesn't....
It is a matter of placement of the increment operation on i that is breaking
the code and has nothing to do with your default answer of "you don't know how
CTFE's work, read the docs!" and "... it's not a compile-time variable".

Hello there. Have you read my answer? The very first one?
1) i will never be incremented there and CTFE has nothing to do
with it.
2) This topic should have been in D.learn
3) If you won't tone down your arrogance, soon there will be no
one left willing to answer you.

The following code inserts properties for each type,
auto name = "Value"~((i == 0) ? "" : to!string(i++));
always as the i == 0 evaluate to true.
My question is, why the heck is it so hard to use basic
programming structs inside CTFE's? I know that CTFE's have to
work at run time also, so there is a limitation, but:
1. obviously ints work because the code below works with i as a
counter but we can't do a simple compare on it... this seems
like a bug.
2. foreach can be used but a simple for loop can't... makes no
sense.
I know what the average response is going to be but hopefully
someone will surprise me with some useful.
mixin template PropertyBuilder(T...)
{
template _(TT...)
{
static string eval()
{
string s;
pragma(msg, TT);
int i = 0;
foreach(t; TT)
{
auto name = "Value"~((i > 0) ? "" : to!string(i++));
s = " property "~t.stringof~" "~name~"();\n";
s ~=" property "~t.stringof~" "~name~"("~t.stringof~"
value);\n";
}
return s;
}
enum _ = eval();
pragma(msg, _);
}
mixin("mixin(_!T);");
}
interface a(MT...)
{
mixin PropertyBuilder!MT;
}

The i++ in to!string not having any effect is rather
surprising, I agree.

Scratch that, there's nothing surprising about it at all. i == 0
on the first iteration and therefore the first branch of the
ternary isn't executed. The same thing happens the next iteration
and so on, leaving i==0 for every iteration.