【问题标题】:Using a std::tuple as key for std::unordered_map使用 std::tuple 作为 std::unordered_map 的键
【发布时间】:2012-07-09 16:06:11
【问题描述】:

使用下面的代码,我在 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&lt;0&gt;(v0) == std::get&lt;0&gt;(v1) &amp;&amp; .....这样比较keys,你可以写return v0==v1
  • @Nawaz:感谢您的评论,我试过了,但我仍然收到错误。
  • 哪一行导致错误,第一行有 make_tuple 还是第二行? IdeOne 错误显示 key_t 被重新定义。尝试重命名类型。

标签: c++ stl compiler-errors tuples unordered-map


【解决方案1】:

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 重命名为其他名称,或将其放入某些命名空间中。

Your code works after this change 在 g++ 和 clang++ 中。我相信这是 MSVC 中的一个错误。

【讨论】:

    【解决方案2】:

    奇怪。您的代码在 Visual Studio 2012 RC 中运行良好,输出为“x: test data”。

    【讨论】:

    • 应该澄清一下,我使用的是 MS Visual Studio 2010。
    • 在 ideone 的错误是 /usr/include/sys/types.h:123:17: error: 'key_t' 有一个先前的声明为 'typedef __key_t key_t',所以它可以与另一个 typedef,但我不知道 2012 VC。
    • 你说得对,我改了类型的名字,用ideone编译,好像msvc有bug:ideone.com/olN9W
    • 所以,我正在 VC 2010 Express 上尝试此代码,它工作正常。
    猜你喜欢
    • 1970-01-01
    • 2020-03-09
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 2016-06-15
    • 2013-05-04
    • 1970-01-01
    相关资源
    最近更新 更多