Re: Is CArray best for this...
"David Wilkinson" <no-reply@effisols.com> wrote in message
news:eNeog7jWIHA.1208@TK2MSFTNGP03.phx.gbl...
I thought we were comparing the STL with the MFC collection classes. I
don't think CMap is any simpler here, and the concepts you list above are
either standard C++ or common to the entire STL.
We were, until I was challenged about what was wrong with STL and I thought
the best way to show that was to show what I thought was an ideal
alternative, which is the .NET collection classes.
Here is the code for MFC:
CMapStringToString map;
POSITION pos =map.GetStartPosition();
CString strName;
CString strValue;
while( pos != NULL )
{
map.GetNextAssoc( pos, strName, strValue );
DoSomething(strValue);
}
This is verbose, but more readable than the STL equivalent to the lack of
C++-isms. You are right that all those things I listed that are too
computer-scientish are standard C++, but that doesn't mean you need to
design a library that goes overboard trying to use as many of them as
possible, when all it does is reduce readability.
In your last paragraph, std::vector does not have this "behind your back"
feature.
Rather, I think you are talking about std::map::operator[](), but what you
say is not true. If you use this operator in your code, the VALUE class
must have a default constructor, or the code will not compile, so no
exception can be thrown if you try to access a non-existent element. If
you do not use this operator you do not need a default constructor.
For some reason, you cannot compile a CMap at all if the value type does
not have a default constructor. But if you do have such a constructor then
the (VC9) documentation for CMap is very confusing:
---------------------------------
VALUE& operator[](
ARG_KEY key
);
<snip>
Remarks
Thus (sic) it can be used only on the left side of an assignment statement
(an l-value). If there is no map element with the specified key, then a
new element is created.
There is no "right side" (r-value) equivalent to this operator because
there is a possibility that a key may not be found in the map. Use the
Lookup member function for element retrieval.
------------------------------
This is nonsense. There is nothing in the C++ language to prevent the
above operator from being used as a r-value. Indeed the following code
runs cleanly:
typedef CMap<int, const int&, int, const int&> IntMap;
IntMap intMap
int n = intMap[0]; // doesn't exist
ASSERT (n == 0);
ASSERT (intMap.GetSize() == 1);
as does the analogous code for std::map.
You may not like this back-door insertion of elements into the map, but
there is really no difference between CMap and std::map in this regard.
This CMap behavior is confusing, I agree. But the doc plainly says that,
like it or not, CMap::operator[] is a substitute for CMap::SetAt() which
plainly operates on an l-value. It's a pain to have to use CMap::Lookup()
for the r-value, but there it is. However, this avoids the behavior I
dislike about having the element inserted just because I referenced it as an
r-value (the only way to reference an r-value is to use Lookup(), and that
does NOT create an element behind your back).
Using CMap::operator[] for an r-value as you did may be legal, but surely
can't be advantageous in real life. Who would want an int of 0 (and why 0
and not some other value) to be inserted into the map when you could be
querying whether it was there? Since CMap::Lookup() returns a bool, it
clearly works the way I want.
-- David