2

Possible Duplicate:
Why isn't the [] operator const for STL maps?

I've boiled this down to (what I think is) its simplest form:

#include <iostream>
#include <map>
#include <vector>

class NumberHolder
{   
public:
    NumberHolder( const std::string aKey, const double aNumber );
    void printSmallestMappedNumber( const unsigned int theIndex ) const;
private:
    std::vector< std::map< std::string, double> > theNamedNumberMapVector;
};

NumberHolder::NumberHolder( const std::string key, const double aNumber )
{
    std::map<std::string, double> aTempMap;
    aTempMap[key] = aNumber;
    theNamedNumberMapVector.push_back(aTempMap);
}

void NumberHolder::printSmallestMappedNumber( const unsigned int theIndex ) const
{
    std::map<std::string, double>& aSpecificMap = theNamedNumberMapVector[theIndex];
    std::cout << aSpecificMap["min"] << std::endl;
}

int main(int argc, char* argv[])
{
    NumberHolder aTaggedNumberHolder("min", 13);
    aTaggedNumberHolder.printSmallestMappedNumber( 0 );
    return 0;
}

I have a vector full of maps, and each map is full of (string) "tagged" numbers. I'm trying to keep as tight of control over access to the visibility/mutability of the variables involved.

Anyhow, the compiler fails with this error

Binding of reference to type 'std::map' to a value of type 'const std::map, double, std::less >, std::allocator, double> > >' drops qualifiers

My first (underbaked) attempt was making the map const..., as I'm not modifying the map, only retrieving a value from it:

const std::map<std::string, double>& aSpecificMap = theNamedNumberMapVector[theIndex];

Which then presents me with this admittedly shorter, but actually a bit more confusering error:

No viable overloaded operator[] for type 'const std::map<std::string, double>'

On the following line instead:

 std::cout << aSpecificMap["min"] << std::endl;

However, perhaps because I've been trying to untangle this for a bit, my solution seems to be awfully, awfully crufty:

std::map<std::string, double>& aSpecificMap = const_cast<std::map<std::string, double>&>(theNamedNumberMapVector[theIndex]);

const_casting away the [const derp] qualifier works around my problem, but I would really like to have a clear understanding of exactly what's going on. I'm guessing that the compiler is disgruntled about my access to the map (in my second attempt, above) and believes that I will use & abuse my access to the map's contents. I'd really like / need to be able to explain stuff like this to other people, as well as trying not to abuse the language and ultimately end up on The Daily WTF, because, you know, shame and stuff.

Community
  • 1
  • 1
hEADcRASH
  • 1,905
  • 17
  • 17
  • 5
    To be quite frank, there's way too much unrelated crap in the question. People don't want to waste time reading all that; they just want the question. – chris May 28 '12 at 03:00
  • Quite sorry, chris .. the topic was really, really dry and I tried to lighten it up a bit on this weekend evening (PST). My attempt at some TL;DRs (in caps even!) apparently failed too - apologies. – hEADcRASH May 28 '12 at 03:05
  • 1
    @hEADcRASH, we still value humour, but not when it really detracts from the actual question. Perhaps the most notable exception is the top-rated C++ question, http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator. If you look around, you'll see comments rated high because they were funny, not because they were helpful. It's all about using it in moderation. – chris May 28 '12 at 03:17
  • Yup, understood (and agree) - it was definitely a (perhaps a username change is in order?) headdesk moment to see the already-asked-in-a-far-far-shorter-post duplicate question link. *thud* – hEADcRASH May 28 '12 at 03:24

2 Answers2

5

If you look at the declaration for map's operator[], you will see that it is not const qualified, which is why it cannot be called on a const std::map<std::string, double>. The reason it is not const is because if the key does not exist in the map, it creates it. You should instead use find or at to get the element.

David Brown
  • 13,336
  • 4
  • 38
  • 55
0

map<>::operator[] creates elements in the map if they don't already exist, which is why it's not allowed on a const object. You should use find().

(Some of the linked-at-right questions already answer this: e.g. Why isn't the [] operator const for STL maps? - I'll vote to close this as a duplicate)

Community
  • 1
  • 1
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Yup, certainly, Tony .. I did a search (honest engine!) and didn't see that .. or missed it - I've been staring at programmer font far too long today. – hEADcRASH May 28 '12 at 03:08