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.

Reply via email to