Hi all, I've encountered a similar situation in my own code, i.e. the compiler chose the non-const version of an operator overload by default, even when the const version was available.
So the problem is that operator[] calls let_op(). Had it called op() like the const operator[] it would have worked (change to "e = const_cast<const ex &>(e)[0];" to verify that).
My work-around is similar, except that I might recommend: static_cast<const T&>(foo)[arg] instead of const_cast, because I wasn't discarding const-ness, but rather *enforcing* it where it was only optional, in a non-const method. This was slightly annoying to write in many places so I wrapped the operation in a less inconvenient wrapper method "const_index(const size_t) const", certainly not as compact as operator overloading, but it gets the job done without ambiguity.
Ok, so the real problem is that there is no way of selecting between the two versions of operator[] based on whether it is used as an rvalue or an lvalue. The const-ness of the target is not a strong enough prerequisite.
Hope this servers as a temporary work-around until a better solution arrives. David Fang Computer Systems Laboratory Electrical & Computer Engineering Cornell University http://www.csl.cornell.edu/~fang/ -- *gag* work in progress