Click to See Complete Forum and Search --> : Mapping objects without a default constructor


Grappler
June 19th, 2008, 03:16 PM
Part of a project I've been working on uses a map. It has the type int as the keys, and an object I made as the values. The object has no default constructor, and when I compile, I get an error that I don't really know how to fix.

I wrote the code below to show the problem..

//maptest.cpp

#include <iostream>
#include <map>
#include <string>
#include "Foo.h"

int main()
{
std::map <int, Foo> foomap;

Foo bar("bar");
Foo gym("gym");

foomap[0] = bar;
foomap[1] = gym;

std::cout << foomap[0].getString() << std::endl;
std::cout << foomap[1].getString() << std::endl;

return 0;
}


//Foo.h

#include <string>

#ifndef FOO
#define FOO

class Foo
{
public:
Foo(std::string s);
~Foo();

std::string getString();

private:
std::string str;
};

#endif


//Foo.cpp

#include <string>
#include "Foo.h"

std::string str;

Foo::Foo(std::string s)
{
str = s;
}

std::string Foo::getString()
{
return str;
}



And here are the compiler errors:

G:\Dev-Cpp\include\c++\3.4.2\bits\stl_map.h In member function `_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = Foo, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, Foo> >]':
13 C:\stuff\C++\test crap\maptest.cpp instantiated from here
339 G:\Dev-Cpp\include\c++\3.4.2\bits\stl_map.h no matching function for call to `Foo::Foo()'
note C:\stuff\C++\test crap\Foo.h:7 candidates are: Foo::Foo(const Foo&)
note C:\stuff\C++\test crap\Foo.h:7 Foo::Foo(std::string)


I understand that the reason it does this is because Foo doesn't have a default constructor. Is there a way around this, or am I just doing something wrong?

laserlight
June 19th, 2008, 03:23 PM
You could try:
foomap.insert(std::make_pair(0, Foo("bar")));
My guess is that
foomap[0] = bar;
causes the default constructor to be invoked, upon which bar is assigned to that new object. Using insert() could circumvent this default construction, if I am not wrong.

jlou
June 19th, 2008, 03:26 PM
I believe you're right laserlight. Note that if you use insert instead of operator[], you must remember that it behaves differently if the key already exists. You may have to use find() to verify that a key is not in the map before inserting it if the rest of the code logic does not guarantee it.

Grappler
June 19th, 2008, 03:46 PM
Works great, thank you. I used foomap.insert, but then it gave me an error when I tried to access it! So instead of using foomap[0], I used foomap.find(0)->second and it works perfectly.

Thanks! =]

STLDude
June 19th, 2008, 05:21 PM
I hope that it's not your actual code. What about if element does not exist? foomap.find(0)->second


std::map<int, Foo>const_iterator it = foomap.find(0);
if (it != foomap.end())
{
Foo myFoo = (*it).second;
// or this if you don't want to make a copy of Foo object
const Foo& myFoo = (*it).second;
}