Discussion:
Operator [] read or write detection
(too old to reply)
tom
2009-09-17 05:40:28 UTC
Permalink
Is there is a programmatic way to determine or detect within a []
operator method when the operator is being used for reading or
writing? Like maybe the compiler is adding some magic value in the
stack that can be checked?

For example:

// assignment
some-collection["key"] = string-value;

// reading
string-value = some-collection["key"];


Thanks

--
Tom
Ulrich Eckhardt
2009-09-17 06:43:30 UTC
Permalink
Post by tom
Is there is a programmatic way to determine or detect within a []
operator method when the operator is being used for reading or
writing?
No.

That said, there are two things to consider:
1. You can overload the operator in a const and non-const version. For the
const version, you then return a const element which then can't be written
to. However, if you have a non-const [reference to a] container, it will
always call the non-const overload.

2. You can return a proxy object which features an assignment operator and a
conversion to the target type. When the assignment operator is called, it
is obviously being assigned to, otherwise only read. Note that you will
have to provide further operations like operator++ if you want "vec[idx]++"
to work.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
tom
2009-09-17 09:12:56 UTC
Permalink
Post by Ulrich Eckhardt
Post by tom
Is there is a programmatic way to determine or detect within a []
operator method when the operator is being used for reading or
writing?
No.
1. You can overload the operator in a const and non-const version. For the
const version, you then return a const element which then can't be written
to. However, if you have a non-const [reference to a] container, it will
always call the non-const overload.
2. You can return a proxy object which features an assignment operator and a
conversion to the target type. When the assignment operator is called, it
is obviously being assigned to, otherwise only read. Note that you will
have to provide further operations like operator++ if you want "vec[idx]++"
to work.
Thanks. I have to explore your input as it relates to [] operators.

While the need was solved using specific access functions, I was able
to just solved it using get/put properties and this provided the same
collection like functionality I was looking for.

If interested, overall, I have a class (a parser) which creates CMap
collection of keys vs CArray strings.

typedef CArray<CString, const char *> TKeyList;
CMap<CString, const char *, TKeyList *, TKeyList *> Headers;

The keys can have duplicates, so the array is used to aggregate the
dupes using the using [] operator allowed for simple assignments:

CString & CMyClass::operator [](const char *s)
{
TKeyList *kl;
if (!Headers.Lookup(s, hl)) {
kl = new TKeyList;
Headers[s] = kl;
}
kl->SetSize(kl->GetSize()+1);
return (*kl)[hl->GetSize()-1];
}

So as you can see, this operator is only useful when building the
collection:

myclass["key1"] = string;
myclass["key3"] = string;
myclass["key3"] = string;
myclass["key1"] = string;
myclass["key2"] = string;

It wasn't designed for reading, so doing this:

last_string = myclass["key1"];

obviously would not work.

What I wanted to do is get the Last entry for a key which I resolved
using a specific GetLast(key) function.

But I used properties to give me the collection [] operator feel:

class CMyClass {
public:
...
CString &operator [](const char *s);
const char * GetLast(const char *szKey, const char *szdef = "");
..
private:
typedef CArray<CString, const char *> TKeyList;
CMap<CString, const char *, TKeyList *, TKeyList *> Headers;
};

const char *CMyClass::GetLast(const char *szKey,
const char *szdef)
{
TKeyList *hl = NULL;
if (Headers.Lookup(szHeader, hl)) {
if (hl->GetSize()) return hl->GetAt(hl->GetSize()-1);
return "";
}
return szdef;
}

class CApplet
{
private:
CMyClass myclass;

public:
_declspec(property(get=getPHeader,put=putPHeader))
CString Header;

virtual CString getPHeader(const char *szKey)
{
return myclass.GetLast(szKey);
}
virtual void putPHeader(const char *szKey, const char *szValue)
{
// assign using current CMyClass [] operator operator
myclass[szKey] = szValue;
}
}


---

Continue reading on narkive:
Loading...