Steve H
Steve H

Reputation: 5519

Trouble adding element to std::map

Foo.h :

class Foo
{
public:
    Foo(void);
    ~Foo(void);   

    void AddScreen(std::string name, ScreenBase &screenToAdd);

private:

    std::map<std::string, ScreenBase> m_screens;
};

Foo.cpp :

void Foo::AddScreen(string name, ScreenBase &screenToAdd)
{
    m_screens[name] = screenToAdd; 
}

the last line creates a compile error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::

commenting out the last line and the compile succeeds.

I'm new to c++ (coming from a managed language) and don't know why I can't populate the map with this.

Any insight is appreciated. Thanks.

ScreenBase.h :

    #pragma once
    class ScreenBase
    {
    public:
        ScreenBase();
        ~ScreenBase();

        virtual void Update(float tt, float dt);
        virtual void Render();
    };

ScreenBase.cpp :

#include "pch.h"
#include "ScreenBase.h"

ScreenBase::ScreenBase(void)
{
}
ScreenBase::~ScreenBase(void)
{
}
void ScreenBase::Update(float tt, float dt)
{

}
void ScreenBase::Render()
{

}

Upvotes: 1

Views: 884

Answers (2)

BeMFi
BeMFi

Reputation: 71

You forgot to add the following line to Foo.cpp

#include <string>

That should fix it.

The reason that fixes it is because the "<" operator between 2 std::string objects is defined there. Since std::map is an associative array, it will sort the keys with either a specific sorting function you specify (as a third parameter for the template, e.g. std::map<int, MyObj, MyIntCompareFunctor>), or it will default to using < operator of the key type which in your case is std::string.

P.S. Also, pass strings by reference, not value: e.g. void foo(const std::string& bar){};

Upvotes: 2

Viktor Latypov
Viktor Latypov

Reputation: 14467

To use some class (like ScreenBase) in an STL container, the class must conform to some specifications (traits). In this case, ScreenBase must be copy-constructible, so you need at least the

ScreenBase(const ScreenBase& src) { CopyFromOther(src); }

void CopyFromOther(const ScreenBase& src) {... do the stuff ... }

copy constructor.

Also one must define the "=" operator for the ScreenBase. IF you already have the copy constructor and it is simply the

ScreenBase& operator = (const ScreenBase& src) { CopyFromOther(src); return *this; }

To avoid asking every possible question about the STL containers you may also read the SGI's documentation on STL. It describes everything you need to use the things like maps/hashtables and anything else.

http://www.sgi.com/tech/stl/


Your comment about the "instances of derived class" gives another insight. Try storing the pointers to ScreenBase then.

So use this:

std::map<std::string, ScreenBase*> m_screens;

There will be no warnings, but of course, extra memory management would be required.

Upvotes: 1

Related Questions