tags:

views:

56

answers:

3

I'm having trouble getting something to compile. I don't understand the error thrown out by the compiler. Some code to illustrate the problem is below.

#include <map>

using namespace std;

class Thing
{
public:
    Thing(int n):val(n) {}

    bool operator < (const Thing& rhs) const
    {
        return val < rhs.val;
    }

    int getVal() { return val; }

private:
    int val;
};


int main(int argc, char* argv[])
{
    std::map<Thing, int> mymap;
    Thing t1(1);
    Thing t2(10);
    Thing t3(5);

    mymap[t1] = 1; // OK

    mymap.insert(t1); // Compile error
}

Now the compiler error message:

test.cpp: In function ‘int main(int, char**)’: test.cpp:34: error: no matching function for call to ‘std::map, std::allocator > >::insert(Thing&)’ /usr/include/c++/4.4/bits/stl_map.h:499: note: candidates are: std::pair, std::_Select1st >, _Compare, typename _Alloc::rebind >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair&) [with _Key = Thing, _Tp = int, _Compare = std::less, _Alloc = std::allocator >] /usr/include/c++/4.4/bits/stl_map.h:539: note: typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename _Alloc::rebind >::other>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(typename std::_Rb_tree<_Key, std::pair, std::_Select1st >, _Compare, typename _Alloc::rebind >::other>::iterator, const std::pair&) [with _Key = Thing, _Tp = int, _Compare = std::less, _Alloc = std::allocator >]

What does that mean? Is there another method or operator I need to define in Thing to make it compile?

+2  A: 

You cannot insert a key (Thing object) by itself - map::insert (on your map at least) take a std::pair<Thing,int> so that you insert value int indexed by key Thing.

However - it looks to me like you actually want to use std::set<Thing>, since your Thing object has its own ordering semantics. Repeating the encapsulated int val as the value in a map keyed by Thing is redundant, and breaks the nice encapsulation you have here.

int main(int argc, char* argv[])
{
    std::set<Thing> myset;
    Thing t1(1);
    Thing t2(10);
    Thing t3(5);

    std::pair<std::set<Thing>::iterator, bool> result = myset.insert(t1);

    std::set<Thing>::iterator iter = myset.find(t1);
}
Steve Townsend
+5  A: 

You need mymap.insert(std::pair<Thing,int>(t1,x));, where x is the value you want to map to t1.

Oli Charlesworth
Yup. Or `mymap.insert(std::make_pair(t1,x));` or `mymap.insert(std::map<Thing,int>::value_type(t1,x))`. That last one gets more useful if you have a `typedef` for `std::map<Thing,int>`.
aschepler
A: 

std::map::insert expects you to pass it a key-value pair.

mymap.insert(std::pair<Thing, int>(t2, 10)); would work.

birryree