www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Can't call opIndex on class property

reply "John C" <johnch_atms hotmail.com> writes:
class NameValue {
    char[][char[]] inner;
    char[] opIndex(char[] name) {
        return inner[name];
    }
    void opIndexAssign(char[] value, char[] name) {
        inner[name] = value;
    }
}

class Client {
    NameValue pairs_;
    this() {
        pairs_ = new NameValue;
    }
    NameValue pairs() {
        return pairs_;
    }
}

void main() {
    Client client = new Client;
    client.pairs["One"] = "Two"; // error here
}

Produces "((client).pairs)()["One"] is not an lvalue".
(Windows XP SP2, DMD 0.150)

Changing the offending line to
    client.pairs()["One"] = "Two"
removes the error, as does this
    client.pairs_["One"] = "Two"
but I'd like to keep it as a property. 
Apr 02 2006
parent reply Aho H. Ullman <Aho_member pathlink.com> writes:
In article <e0pmst$1ivn$1 digitaldaemon.com>, John C says...
    NameValue pairs() {
        return pairs_;
    }
but I'd like to keep it as a property. 

Properties are defined to be variables or functions, that can be treated as variables, i.e. functions with at most one argument. You have two arguments and therefore this is not possible in the current version of D. Maybe resembling the original structure solves your design goal class Pairs{ void opIndexAssign(char[] value, char[] name) { pairs_[name] = value; } } Pairs pairs; this() { pairs= new Pairs; } with the call client.pairs["One"] = "Two"; // no error here
Apr 04 2006
parent reply "John C" <johnch_atms hotmail.com> writes:
"Aho H. Ullman" <Aho_member pathlink.com> wrote in message 
news:e0ukrd$27ub$1 digitaldaemon.com...
 In article <e0pmst$1ivn$1 digitaldaemon.com>, John C says...
    NameValue pairs() {
        return pairs_;
    }
but I'd like to keep it as a property.

Properties are defined to be variables or functions, that can be treated as variables, i.e. functions with at most one argument. You have two arguments and therefore this is not possible in the current version of D.

Surely I have no arguments - pairs["Name"] = value should be equivalent to pairs()["Name"] = value.
 Maybe resembling the original structure solves your design goal

No, because I want the 'pairs' property to be read-only - that is, users can assign values to names, but not override the internal variable.
 class Pairs{
 void opIndexAssign(char[] value, char[] name) {
 pairs_[name] = value;
 }
 }
 Pairs pairs;
 this() {
 pairs= new Pairs;
 }

 with the call

 client.pairs["One"] = "Two"; // no error here

Wait - didn't I already show in my original post that it works if the variable is used instead?
Apr 04 2006
parent Aho H. Ullman <Aho_member pathlink.com> writes:
In article <e0uqau$2g5q$1 digitaldaemon.com>, John C says...
Surely I have no arguments - pairs["Name"] = value should be equivalent to 
pairs()["Name"] = value.

A property with no arguments is defined to be a getter, so you get the "not an lvalue"-error and are not able to assign. And if you want a setter you have to use one argument, i.e. you are loosing the syntactical appearance of an AA.
I want the 'pairs' property to be read-only - that is, users can 
assign values to names, but not override the internal variable.

Wait - didn't I already show in my original post that it works if the 
variable is used instead? 

I haven't clearly expressed what I mean with _resemble_. I meant to introduce another unprotected variable that implements the protection for the protected internal variable. That unprotected variable is assignable, but the only possible assignment is eliminating every access to the internal variable. This may solve your primary design goals, but at the cost that every access to the internal variable is sabotageable by a black hat. ---- file "propAA.d" import std.stdio; class NameValue { char[][char[]] inner; char[] opIndex(char[] name) { return inner[name]; } void opIndexAssign(char[] value, char[] name) { inner[name] = value; } } class Client { private: NameValue pairs_; class Pairs{ void opIndexAssign(char[] value, char[] name) { pairs_[name] = value; } char[] opIndex( char[] name){ return pairs_[ name]; } } public: Pairs pairs; this() { pairs_ = new NameValue; pairs = new Pairs; } } Client client; ------file "user.d" import propAA; void main() { Client client = new Client; // client.pairs_["One"]="One"; // error: protected // client.pairs= new Client.Pairs; // at least ineffective // client.pairs= null; // this sabotages every access client.pairs["One"] = "Two"; // no error here writefln( client.pairs["One"]); // assigned }
Apr 05 2006