Comment #0 by john.loughran.colvin — 2013-12-04T14:05:46Z
this code:
template PartialApply(alias F, uint argLoc, Arg ...)
if(Arg.length == 1)
{
pragma(msg, "\nPartialApply!(", __traits(identifier, F),", ", argLoc, ", ", Arg[0], ");\n");
template PartialApply(L ...)
{
pragma(msg, "\nPartialApply!(", __traits(identifier, F),", ", argLoc, ", ", Arg[0], ").PartialApply!(", L, ");\n");
alias PartialApply = F!(L[0 .. argLoc], Arg, L[argLoc .. $]);
}
}
struct Pack(T...)
{
template opDispatch(string s)
{
pragma(msg, "\n",typeof(this),".opDispatch!(\"",s,"\");\n");
mixin("alias opDispatch = PartialApply!(." ~ s ~ ", 0, typeof(this));");
}
}
struct asArg(T, uint argIndex)
{
pragma(msg, "\n", typeof(this));
pragma(msg, "asArg!(", T, ", ", argIndex, ");\n");
template opDispatch(string s)
{
pragma(msg, "\n",typeof(this),".opDispatch!(\"", s, "\");\n");
mixin("alias opDispatch = PartialApply!(." ~ s ~ ", " ~ argIndex.stringof ~ ", T);");
}
}
unittest
{
pragma(msg, "\n" ,Pack!(1,2,3).asArg!(1).Pack!(0), "\n");
alias A = Pack!(1,2,3).asArg!(1).Pack!(0);
}
produces this output:
$ dmd -unittest -c break.d
Pack!(1, 2, 3).opDispatch!("asArg");
PartialApply!(asArg, 0u, Pack!(1, 2, 3));
PartialApply!(asArg, 0u, Pack!(1, 2, 3)).PartialApply!(tuple(1));
F!(Pack!(1, 2, 3), 1)
asArg!(Pack!(1, 2, 3), 1u);
F!(Pack!(1, 2, 3), 1).opDispatch!("Pack");
PartialApply!(Pack, 1u, Pack!(1, 2, 3));
PartialApply!(Pack, 1u, Pack!(1, 2, 3)).PartialApply!(tuple(0));
F!(0, Pack!(1, 2, 3))
break.d(12): Error: struct break.Pack!(1, 2, 3).Pack template identifier 'asArg' is not a member of 'struct Pack'
break.d(12): Error: struct break.Pack!(1, 2, 3).Pack template identifier 'asArg' is not a member of 'struct Pack'
A few things jump out, other than the (hopefully) obvious rejects-valid:
1) The two lines
F!(Pack!(1, 2, 3), 1)
asArg!(Pack!(1, 2, 3), 1u);
should be the same. How can a struct not be able to work out it's own typeof(this)?
2) There is an extra new-line at the top of the output and a missing new-line between the last two pragma printouts.
Comment #1 by john.loughran.colvin — 2013-12-04T14:09:12Z
Also, note that it manages to print something halfway-correct for the unittest pragma(msg, ...) even though it claims a much earlier error.
A clean version of the code without all the pragmas:
template PartialApply(alias F, uint argLoc, Arg ...)
if(Arg.length == 1)
{
template PartialApply(L ...)
{
alias PartialApply = F!(L[0 .. argLoc], Arg, L[argLoc .. $]);
}
}
struct Pack(T...)
{
template opDispatch(string s)
{
mixin("alias opDispatch = PartialApply!(." ~ s ~ ", 0, typeof(this));");
}
}
struct asArg(T, uint argIndex)
{
template opDispatch(string s)
{
mixin("alias opDispatch = PartialApply!(." ~ s ~ ", " ~ argIndex.stringof ~ ", T);");
}
}
unittest
{
alias A = Pack!(1,2,3).asArg!(1).Pack!(0);
}
Comment #2 by john.loughran.colvin — 2014-01-15T02:20:11Z
An update:
The clean version above is now a simple rejects-valid.
If you place a pragma(msg, A); in the unittest then it prints the correct thing, but the error saying "template identifier 'asArg' is not a member of 'struct Pack'" is still triggered.
Comment #3 by john.loughran.colvin — 2014-03-15T08:31:54Z
An even more reduced test-case:
template C(alias F)
{
template C()
{
alias C = F;
}
}
struct A
{
template opDispatch(string s)
{
mixin("alias opDispatch = C!(." ~ s ~ ");");
}
}
struct B
{
enum blah = 42;
}
unittest
{
alias Q = A.B!();
pragma(msg, Q.blah);
}
$ rdmd -unittest break.d
break.d(9): Error: struct break.A template identifier 'B' is not a member of 'struct A'
break.d(9): Error: struct break.A template identifier 'B' is not a member of 'struct A'
42
Failed: ["dmd", "-unittest", "-v", "-o-", "break.d", "-I."]
As you can see, it knows the answer, but it is unnecessarily throwing an error.
Comment #4 by john.loughran.colvin — 2014-03-15T09:47:01Z
*** This issue has been marked as a duplicate of issue 12373 ***