Question

The following compiles fine in Visual Studio 08, but when I upgraded to Visual Studio 10 it no longer compiles. I don't have a clue as to exactly what is causing this as the error (at least to me) is not very helpful. This is in a large project, so I got the same error to happen in a small test case as shown below. Any ideas?

MyHash.h

#ifndef __MyHash_h__
#define __MyHash_h__

#include <string>
#include <tuple>
#include <hash_map>
#include <boost/functional/hash.hpp>

typedef std::tr1::tuple<std::string, unsigned int, std::string> Identifier;

class ValueNode {
public:
   ValueNode() { str = "TEST"; }
   virtual ~ValueNode() { }
   std::string getStr() { return str; }
private:
   std::string str;
};

template<> inline 
size_t stdext::hash_value<Identifier>(Identifier const& id)
{
   size_t seed = 0xffff0000;
   boost::hash_combine(seed, std::tr1::get<0>(id));
   boost::hash_combine(seed, std::tr1::get<1>(id));
   boost::hash_combine(seed, std::tr1::get<2>(id));
   return seed;
}

class HashMapClass {
private:
   typedef stdext::hash_map<Identifier, ValueNode> MyMap;

public:
   HashMapClass() { }
   virtual ~HashMapClass() { }
   void meshAround();

private:
   MyMap  mMap;
};

#endif // __MyHash_h__

Main.cpp:

#include "MyHash.h"

void HashMapClass::meshAround() {
   ValueNode test;
   Identifier id("HEYY", 140, "THERE");
   mMap[id] = test;
}

int main() {
   std::cout << "HEY" << std::endl;

   HashMapClass hash1;
   hash1.meshAround();

   std::cout << "EXIT" << std::endl;
   return 0;
}

Error:

1>c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\tuple(127): error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'const Identifier' to 'const std::basic_string<_Elem,_Traits,_Ax> &'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          Reason: cannot convert from 'const Identifier' to 'const std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxtuple0(9) : see reference to function template instantiation 'std::tr1::_Cons_node<_Car,_Cdr>::_Cons_node<_Ty,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&>(_Farg0 &&,_Farg1,_Farg2,_Farg3,_Farg4,_Farg5,_Farg6,_Farg7,_Farg8,_Farg9)' being compiled
1>          with
1>          [
1>              _Car=std::string,
1>              _Cdr=std::tr1::_Cons_node<unsigned int,std::tr1::_Cons_node<std::string,std::tr1::_Tuple_type<std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>::_Type>>,
1>              _Ty=Identifier,
1>              _Farg0=Identifier,
1>              _Farg1=std::tr1::_Nil &,
1>              _Farg2=std::tr1::_Nil &,
1>              _Farg3=std::tr1::_Nil &,
1>              _Farg4=std::tr1::_Nil &,
1>              _Farg5=std::tr1::_Nil &,
1>              _Farg6=std::tr1::_Nil &,
1>              _Farg7=std::tr1::_Nil &,
1>              _Farg8=std::tr1::_Nil &,
1>              _Farg9=std::tr1::_Nil &
1>          ]
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\utility(145) : see reference to function template instantiation 'std::tr1::tuple<_Arg0,_Arg1,_Arg2>::tuple<const std::tr1::tuple<_Arg0,_Arg1,_Arg2>>(_Farg0 &&)' being compiled
1>          with
1>          [
1>              _Arg0=std::string,
1>              _Arg1=unsigned int,
1>              _Arg2=std::string,
1>              _Farg0=const std::tr1::tuple<std::string,unsigned int,std::string>
1>          ]
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\utility(142) : while compiling class template member function 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base(const std::tr1::tuple<_Arg0,_Arg1,_Arg2> &&,ValueNode &&)'
1>          with
1>          [
1>              _Ty1=const Identifier,
1>              _Ty2=ValueNode,
1>              _Arg0=std::string,
1>              _Arg1=unsigned int,
1>              _Arg2=std::string
1>          ]
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\utility(174) : see reference to class template instantiation 'std::_Pair_base<_Ty1,_Ty2>' being compiled
1>          with
1>          [
1>              _Ty1=const Identifier,
1>              _Ty2=ValueNode
1>          ]
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\hash_map(206) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1>          with
1>          [
1>              _Ty1=const Identifier,
1>              _Ty2=ValueNode
1>          ]
1>          c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\hash_map(203) : while compiling class template member function 'ValueNode &stdext::hash_map<_Kty,_Ty>::operator [](const std::tr1::tuple<_Arg0,_Arg1,_Arg2> &)'
1>          with
1>          [
1>              _Kty=Identifier,
1>              _Ty=ValueNode,
1>              _Arg0=std::string,
1>              _Arg1=unsigned int,
1>              _Arg2=std::string
1>          ]
1>          c:\-----------------------\MyHash.h(41) : see reference to class template instantiation 'stdext::hash_map<_Kty,_Ty>' being compiled
1>          with
1>          [
1>              _Kty=Identifier,
1>              _Ty=ValueNode
1>          ]
Was it helpful?

Solution

As per the comment above, this looks to be a bug in VC 2010. (placing objects deriving from tuple into a vector in C++) I've switched from using a tuple to a small class and the error goes away. For completeness, here is the new class:

class Identifier {
public:
   Identifier(std::string a1, unsigned int a2, std::string a3) : arg1(a1), arg2(a2), arg3(a3) { }

   std::string getArg1() const { return arg1; }
   unsigned int getArg2() const { return arg2; }
   std::string getArg3() const { return arg3; }

private:
   std::string arg1;
   unsigned int arg2;
   std::string arg3;
};


inline bool operator< (const Identifier& lhs, const Identifier& rhs) {
   return (lhs.getArg1() < rhs.getArg1() && lhs.getArg2() < rhs.getArg2() && lhs.getArg3() < rhs.getArg3());
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top