On Thursday, 21 November 2013 at 07:23:09 UTC, Jonathan M Davis
wrote:
On Wednesday, November 20, 2013 23:49:42 Spott wrote:
I've been screwing around with templates lately, and I'm
attempting to figure out why the following won't compile:
struct value
{
int a;
const auto
opBinary(string op, T)(in T rhs) const pure {
static if (op == "+")
return
intermediateValue!(value.plus,this,rhs)();
}
ref value opAssign(T)( in T t ) {
a = t.a;
return this;
}
static
int plus(T1, T2)(in T1 x, in T2 y) pure {
return x.a + y.a;
}
}
struct intermediateValue(alias Op, alias A, alias B)
{
auto opBinary(string op, T)(in T rhs) const pure {
static if (op == "+")
return intermediateValue!(value.plus,this,rhs)();
}
@property auto a() const pure {
return Op(A, B);
}
}
void main()
{
value a = value(2);
value b = value(3);
value c;
c = a + b;
}
The error is:
d_playground.d(34): Error: pure nested function 'a' cannot
access
mutable data 'this'
d_playground.d(34): Error: pure nested function 'a' cannot
access
mutable data 'this'
d_playground.d(10): Error: template instance
d_playground.value.opBinary!("+",
value).opBinary.intermediateValue!(plus, this, rhs) error
instantiating
d_playground.d(44): instantiated from here:
opBinary!("+",
value)
d_playground.d(44): Error: template instance
d_playground.value.opBinary!("+", value) error instantiating
What is going on? Why is 'a' not allowed to "access" mutable
data (even though it isn't modifying it)? How do I tell the
compiler to pass "this" in a const fashion?
pure functions can only access their arguments and
global/static constants.
a's only argument is its invisible this pointer. Op, A, and B
are aliases to
stuff outside of a. I suppose that an argument could be made
that because
the're template arguments to the type that a is a part of that
they should be
considered to be arguments to a like the this pointer is, but
you are
essentially trying to have it access data which is not one of
its arguments
and that violates purity.
But all in all, I find your code quite bizarre and difficult to
understand -
particularly your use of aliases - so it's kind of hard for me
to say how
valid it is. I'm surprised that you can get away with feeding a
purely runtime
argument to a template as an alias (namely rhs). I wouldn't
have thought that
that would be valid. In most cases, all template alias
parameters get used for
is passing in predicates to functions (which are almost
invariably delegates
or lambdas). So, clearly my understanding of how alias template
parameters
work is too limited.
- Jonathan M Davis
Why is rhs a purely runtime argument? I would think it would be
known at compile time.