Accessing mutable data that isn't

Jonathan M Davis jmdavisProg at gmx.com
Wed Nov 20 23:22:57 PST 2013


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


More information about the Digitalmars-d-learn mailing list