0
votes

i got some issues trying to convert my map into a set I got a "Chanson" object with this member data :

std::map<std::string,Artiste*> m_interpretes;

Here is how i add my *Artiste to my map :

void Chanson::addArtiste(Artiste* a) throw (ExceptionArtiste, ExceptionLangueIncompatible)
{
    if(a!=NULL)
    {
        if(a->getLangue() == this->getLangue())
        {
            m_interpretes.insert(pair<string, Artiste*>(a->getNom(), a));
            //m_interpretes[a->getNom()] = a;
        }
        else
        {
            throw ExceptionLangueIncompatible(a,this);
        }
    }
}




set<Artiste*> Chanson::getArtistes() const
{
    //set<Artiste*> machin;
    return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
}

i got this error due to this function :

Error C2664: 'std::pair<_Ty1,_Ty2> std::set<_Kty>::insert(Artiste *&&) : impossible de convertir le paramètre 1 de const std::pair<_Ty1,_Ty2> en 'Artiste *&&' c:\program files (x86)\microsoft visual studio 11.0\vc\include\set 179 1

Any idea how to fix it?

3
why are you storing pointers in a container? this seems like a memory leak waiting to happen.Mgetz
Second question: Why are you using dynamic exception specifications? They cause all sorts of strange things to happen and slow down your code, general advice at the moment is to avoid them completely.Mgetz
In fact, in the latest standard, dynamic exception specifications are deprecated.eerorika
@user2079303: Actually, they were deprecated in the previous standard!Lightness Races in Orbit
@LightnessRacesinOrbit well, they still remain deprecated, unless I've missed something.eerorika

3 Answers

6
votes

A map is an associative data structure, while a set only contains unordered collection of items, so adding a pair (key, value) is invalid for the latter and only holds for the former.

To make a set of keys from a map, you can do

std::set<Artiste*> tempSet;
std::transform(m_interpretes.cbegin(), m_interpretes.cend(),
               std::inserter(tempSet, tempSet.begin()),
               [](const std::pair<std::string, Artiste*>& key_value)
               { return key_value.second; });
return tempSet;
4
votes

The std::set constructor you are trying to use will try to construct an element from everything the range you pass it:

return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());

But the element type of that range is

std::pair<const std::string, Artiste*>

which is definitely not convertible to Artiste*, which is why you are getting that error about not being able to convert. You could just do it manually though:

std::set<Artiste*> s;
for (const auto& pair : m_interpretes) {
    s.insert(pair.second);
}
2
votes

The problem is here:

return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());

If you have a look at the types you get from the map::begin() and map::end() functions you see that you get an iterator of std::pair<string, Artiste*>.

The problem is that the set::insert() function expects the iterators it is given to be of type Artiste*.

The simplest fix would be to create the set with a for loop, as shown in Barry's answer.