13

With the code below, I get a very confusing error in MSVC that seems to suggest the key type (an std::tuple) is being converted to an std::string.

#include <iostream>
#include <string>
#include <tuple>
#include <utility>
#include <unordered_map>

typedef std::tuple<std::string,int,char> key_t;

struct key_hash : public std::unary_function<key_t, std::size_t>
{
   std::size_t operator()(const key_t& k) const
   {
      return std::get<0>(k)[0] ^ std::get<1>(k) ^ std::get<2>(k);
   }
};

struct key_equal : public std::binary_function<key_t, key_t, bool>
{
   bool operator()(const key_t& v0, const key_t& v1) const
   {
      return (
               std::get<0>(v0) == std::get<0>(v1) &&
               std::get<1>(v0) == std::get<1>(v1) &&
               std::get<2>(v0) == std::get<2>(v1)
             );
   }
};

struct data
{
   std::string x;
};

typedef std::unordered_map<key_t,data,key_hash,key_equal> map_t;


int main()
{
   map_t m;
   data d;
   d.x = "test data";
   m[std::make_tuple("abc",1,'X')] = d;
   auto itr = m.find(std::make_tuple(std::string("abc"),1,'X'));
   if (m.end() != itr)
   {
      std::cout << "x: " << itr->second.x;
   }
   return 0;
}

Error:

Error   1   error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'const std::tr1::tuple<_Arg0,_Arg1,_Arg2>' to 'const std::basic_string<_Elem,_Traits,_Ax> &'  c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\tuple    127 1   

Compiler: MS Visual Studio 2010

On ideone, I get the following even more convoluted error:

http://ideone.com/yEv2j

I can't seem to figure out where I've gone wrong.

Gerdiner
  • 1,435
  • 3
  • 15
  • 19
  • Note that you don't need to compare the keys like `std::get<0>(v0) == std::get<0>(v1) && .....` Instead you can just write `return v0==v1`. – Nawaz Jul 10 '12 at 08:01
  • @Nawaz: Thanks for the comment, I tried it but I'm still getting the error. – Gerdiner Jul 10 '12 at 08:03
  • Which line is causing the error, the first having make_tuple or the second one? IdeOne error shows key_t being redefined. Try renaming the type. – Ajay Jul 10 '12 at 08:06

2 Answers2

4

The problem for ideone is that key_t already exists:

prog.cpp:7:42: error: conflicting declaration 'typedef class std::tuple<std::basic_string<char>, int, char> key_t'
/usr/include/sys/types.h:123:17: error: 'key_t' has a previous declaration as 'typedef __key_t key_t'

Rename your key_t to something else, or put it into some namespaces.

Your code works after this change in both g++ and clang++. I believe this is a bug in MSVC.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
2

Strange. Your code works fine in Visual Studio 2012 RC and output is "x: test data".

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Should have clarified, I'm using MS visual studio 2010. – Gerdiner Jul 10 '12 at 08:01
  • At the ideone error is that /usr/include/sys/types.h:123:17: error: 'key_t' has a previous declaration as 'typedef __key_t key_t', so it will works with another typedef, but i don`t know about 2012 VC. – ForEveR Jul 10 '12 at 08:04
  • you're right, I change the name of the type and it compiled with ideone, seems like there could be a bug in msvc: http://ideone.com/olN9W – Gerdiner Jul 10 '12 at 08:07
  • so, i`m trying this code on VC 2010 Express and it works fine. – ForEveR Jul 10 '12 at 08:09