On Wednesday, March 21, 2012 11:29:14 H. S. Teoh wrote: > A question was asked on the d-learn forum about why this throws a > RangeError: > > int[string][int] map; > map["abc"][20]++; > > This is understandable, since the compiler translates the second line to: > > map.opIndex("abc").opIndexUnary!"++"(20); > > Since map["abc"] doesn't exist yet, opIndex throws RangeError before we > ever get to the ++. > > I'd like to propose the following fix: if a given chained indexing > expression has any operator applied to its final result (either a unary > operator like ++ or --, or an assignment operator like +=), then instead > of translating previous indexes into opIndex, the compiler should map it > to a new operator overload, say opIndexCreate, which creates the > relevant entry with default value if it doesn't exist yet. That is to > say: > > map["abc"][20]++; > > should be translated to: > > map.opIndexCreate("abc").opIndexUnary!"++"(20); > > where opIndexCreate looks something like: > > Slot opIndexCreate(Key k) { > Slot *s = findSlot(k); > if (s is null) { > s = createNewSlot(k); > } > return s; > } > > Similar changes should be made for expressions like a[b][c][d]=100, or > a[b][c][d]+=100. > > In other words, if the tail of a chain of indexing operations maps to > opIndexAssign, opIndexUnary, or opIndexOpAssign, then all preceding > opIndex calls should be converted to opIndexCreate instead. > > Comments?
IMHO, it's _horrible_ that C++ creates entries in a std::map when you ask for values that aren't there. A RangeError is _exactly_ what should be happening here. There's no element to increment, because it hasn't been added yet. I think that the current behavior is very much what the behavior _should_ be. - Jonathan M Davis