Search code examples
c++c2664

Map insert results in C2664 error in VS 2015, works in VS 2013


This piece of code was working perfectly in VS 2013 but I had to update to VS 2015 and now it throws an error.

I did read https://msdn.microsoft.com/en-us/library/s5b150wd.aspx and googled quite a bit however I still have no idea how to fix this.

I'm using eigen math library to do some 3d math stuff. Eigen's Vector3d class cannot be used as a key to containers so I created my own Vector3dLite class to get around this issue.

class Vector3dLite
{
public:
float VertX, VertY,VertZ;
Vector3dLite(Vector3d& InputVert)
{
    VertX = static_cast<float>(InputVert.x());
    VertY = static_cast<float>(InputVert.y());
    VertZ = static_cast<float>(InputVert.z());
}

Vector3dLite(Vector3dLite& InputVert)
{
    VertX = InputVert.VertX;
    VertY = InputVert.VertY;
    VertZ = InputVert.VertZ;
}
//more operator overloading stuff below
}

Here's where compiler throws the error

map<Vector3dLite, int>  VertexIds;
int unique_vertid = 0;
VertexIds.insert(make_pair(Vector3dLite(tri.Vert1), unique_vertid)); //This line
// Vert1 is an eigen Vector3d object
//...

Here's the compiler error:

error C2664: cannot convert argument 1 from 'std::pair<Vector3dLite,int>' to 'std::pair<const _Kty,_Ty> &&'
      with
      [
          _Kty=Vector3dLite,
          _Ty=int,
          _Pr=std::less<Vector3dLite>,
          _Alloc=std::allocator<std::pair<const Vector3dLite,int>>
      ]
      and
      [
          _Kty=Vector3dLite,
          _Ty=int
      ]

I did try writing const before Vector3dLite object but apparently syntax is not correct.

VertexIds.insert(make_pair(const Vector3dLite(tri.Vert1), unique_vertid));


Solution

  • Since the value type for a map has const object as the first element (the map key), you generally can't use make_pair to construct the value, as the inferred type will not be const.

    You can create a pair with explicit types:

    std::pair<const Vector3dLite, int>(Vector3dLite(tri.Vert1), unique_vertid)
    

    You can use the map's type

    std::map<Vector3dLite, int>::value_type(Vector3dLite(tri.Vert1), unique_vertid)
    

    Or you can create a named const object to use is make_pair

    const Vector3dLite mapkey(tri.Vert1);
    make_pair(mapkey, unique_vertid);
    

    One other note: Your constructors should take their parameters by const &.