Вопрос

I'm experiencing an constness issue when attempting to insert a pair into a map. The compiler error is:

              c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(2089) : see reference to function template instantiation 'std::pair<_Ty1,_Ty2> &std::pair<_Ty1,_Ty2>::operator =(const std::pair<_Ty1,_Ty2> &)' being compiled
1>          with
1>          [
1>              _Ty1=const Assets::AssetId,
1>              _Ty2=std::shared_ptr<Assets::Material>
1>          ]
1>          c:\fusionengine\meshgl.cpp(85) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1>          with
1>          [
1>              _Ty1=const Assets::AssetId,
1>              _Ty2=std::shared_ptr<Assets::Material>
1>          ]

The line causing the error is:

m_materials.insert( MaterialsMap::value_type(pMaterial->AssetId(), pMaterial) );

The m_materials map is declared as follows:

typedef std::map< Assets::AssetId, std::shared_ptr<Material> > MaterialsMap;    
typedef std::pair< Assets::AssetId, std::shared_ptr<Material> > MtlPair;

MaterialsMap  m_materials;

Error 1 error C2166: l-value specifies const object c:\program files (x86)\microsoft visual studio 11.0\vc\include\utility 114

Can anyone explain how I resolve this issue?

Это было полезно?

Решение 2

This code compiles fine with GCC:

#include <map>
#include <memory>
using namespace std;

typedef int AssetId;
struct Material {
    int _id;
    Material(int id) : _id(id) {}
    int AssetId() const { return _id; }
};
typedef std::map< AssetId, std::shared_ptr<Material> > MaterialsMap;    

MaterialsMap  m_materials;

int main() {
    std::shared_ptr<Material> pMaterial(new Material(42));
    m_materials.insert( MaterialsMap::value_type(pMaterial->AssetId(), pMaterial) );
}

Either your example is incomplete or wrong, or this is a bug in the implementation of the standard library of MSVC2012. It shall not call operator= in the above code.

Другие советы

I tore my hair out over this issue, I probably spent on and off a week on it. Luckily it wasn't critical to the project roadmap, so it didn't prevent from continuing.

The issue was not compiler related, although the error reporting could do with enhancement, although I realise that that's always been an issue with template (and STL) code.

So I had an std::copy in my operator= overload to copy the contents of one map to another. Little did I know that this is a no-no.

I finally found this out by building the entire class up again, line by line and function by function, in order to isolate the problem area.

Then by examining the problem area and googling, stackoverflow came to the rescue with this question and answer.

While the following statement is illegal, it is not highlighted as an error in the VS2012 IDE, nor does the compiler identify it as a problem statement.

std::copy( map1.begin(), map1.end(), map2.begin() );

As the previously highlighted SO answer states, the correct way to do this is with an insert statement:

map2.insert( map1.begin(), map1.end() );

I hope this helps someone out there :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top