使用std::tuple作为std::unordered_map的键

13
使用下面的代码,我在MSVC中得到一个非常令人困惑的错误,似乎暗示着键类型(std::tuple)被转换为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   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   

编译器: MS Visual Studio 2010

在ideone上,我得到以下更加复杂的错误:

http://ideone.com/yEv2j

我似乎无法找出我错在哪里了。


请注意,您不需要像 std::get<0>(v0) == std::get<0>(v1) && ..... 这样比较键。相反,您可以只写 return v0==v1 - Nawaz
@Nawaz:感谢您的评论,我尝试了,但仍然出现错误。 - Gerdiner
哪一行导致了错误,是第一个make_tuple还是第二个?IdeOne错误显示key_t被重新定义。尝试重命名类型。 - Ajay
2个回答

4
问题在于 ideone 中已经存在 key_t:
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'

将你的 key_t 重命名为其他名称,或将其放入某些命名空间中。 更改后,您的代码可以在g++和clang++中正常工作。我认为这是MSVC中的一个bug。

2

很奇怪。你的代码在Visual Studio 2012 RC中运行良好,输出是"x:测试数据"。


应该澄清一下,我正在使用的是MS Visual Studio 2010。 - Gerdiner
在ideone上的错误是/usr/include/sys/types.h:123:17: error: 'key_t'已经被声明为'typedef __key_t key_t',因此它将与另一个typedef一起工作,但我不知道2012 VC。 - ForEveR
你说得对,我改了类型的名称后,在ideone上编译通过了,看起来msvc可能存在bug:http://ideone.com/olN9W - Gerdiner
所以,我正在尝试在VC 2010 Express上运行这段代码,它可以正常工作。 - ForEveR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接