【问题标题】:std::for_each no known conversion for argument 1 from 'std::pair<const point, int>' to 'std::pair<point, int>&'std::for_each 没有已知的参数 1 从 'std::pair<const point, int>' 到 'std::pair<point, int>&' 的转换
【发布时间】:2018-05-28 09:43:58
【问题描述】:

我无法理解,因为这两种情况看起来如此相似,在第一个 for_each 我无法获得对 pair 的引用,而在第二个我得到对 pair 的引用而没有大惊小怪。谁能给我解释一下?

#include <unordered_map>
#include <cstring>
#include <algorithm>
#include <iostream>

struct table_info_t {
    char name[32] = {0};
    int posx;
    int posy;

    table_info_t(const char *name, int posx, int posy) : posx(posx), posy(posy) {
        strncpy(this->name, name, 31);
    }
};

struct point {
    int posx;
    int posy;

    point(int posx, int posy) : posx(posx), posy(posy) { }
};

size_t hashstruct(const char* hptr, size_t size) {
    size_t h = 31;
    for (size_t i = 0; i < size; i++) {
        h = (h + *hptr) * 31;
        hptr++;
    }
    return h;
}

#define MAP_OPERATORS(typ)\
namespace std {\
\
    template<>\
    struct hash<typ> {\
        std::size_t operator()(const typ &k) const { return hashstruct((const char*)&k, sizeof(typ)); }\
    };\
\
    bool operator==(const typ& one, const typ& other) { return memcmp(&one, &other, sizeof(typ)) == 0; }\
};

MAP_OPERATORS(point); //hash structure and operator==
MAP_OPERATORS(table_info_t); //hash structure and operator==

int main(int argc, char** argv) {
    std::unordered_map<point, int> sp;
    sp[point(3, 4)] = 7;
    std::for_each(sp.begin(), sp.end(),
                  [](std::pair<point, int> pair) {
                      std::cout << pair.first.posx << "+" <<pair.first.posy << "=" << pair.second << "\n";
                  });

    std::unordered_map<table_info_t, const char *> m;
    m[table_info_t("make my day", 3, 14)] = "make my day 3,14";

    std::for_each(m.begin(), m.end(),
                  [](std::pair<const table_info_t, const char * >& pair)
                  {
                      std::cout << pair.first.name << pair.first.posx << pair.first.posy << " " << pair.second << "\n";
                  }
    );

    return 0;
}

两种结构差别不大,但是在编译时,我得到了这个错误:

In file included from .../4.8.2/include/c++/4.8.2/algorithm:62:0,
                 from .../src/main/c/hashtable.cpp:10:
.../4.8.2/include/c++/4.8.2/bits/stl_algo.h: In instantiation of '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = std::__detail::_Node_iterator<std::pair<const point, int>, false, true>; _Funct = main(int, char**)::__lambda0]':
.../src/main/c/hashtable.cpp:45:24:   required from here
.../4.8.2/include/c++/4.8.2/bits/stl_algo.h:4417:14: error: no match for call to '(main(int, char**)::__lambda0) (std::pair<const point, int>&)'
  __f(*__first);
              ^
.../src/main/c/hashtable.cpp:43:24: note: candidates are:
                       [](std::pair<point, int> &pair) {
                        ^
In file included from .../4.8.2/include/c++/4.8.2/algorithm:62:0,
                 from .../src/main/c/hashtable.cpp:10:
.../4.8.2/include/c++/4.8.2/bits/stl_algo.h:4417:14: note: void (*)(std::pair<point, int>&) <conversion>
  __f(*__first);
              ^
.../4.8.2/include/c++/4.8.2/bits/stl_algo.h:4417:14: note:   candidate expects 2 arguments, 2 provided
.../src/main/c/hashtable.cpp:43:53: note: main(int, char**)::__lambda0
                       [](std::pair<point, int> &pair) {
                                                     ^
.../src/main/c/hashtable.cpp:43:53: note:   no known conversion for argument 1 from 'std::pair<const point, int>' to 'std::pair<point, int>&'   

我需要删除引用。然而,对 pair 的引用对于第二个 for_each 中的编译器来说非常好。

【问题讨论】:

  • @Someprogrammerdude const table_info_t是正确的,键类型有const,错误来自第一个for_each
  • 感谢@PasserBy 我修复了缺少 lt 和 gt 标签的错误描述,所以现在更清楚错误是什么了。
  • @user_pj 不要在 cmets 中发布代码!编辑您的问题以确保您的Minimal, Complete, and Verifiable Example 确实完整且可验证。并且在编辑问题时,请将编译器和/或链接器的 fullcomplete 输出也复制粘贴到问题正文中。然后在代码中标出错误所在的行,例如评论。
  • 谢谢@Someprogrammerdude - 解决了这个问题。
  • 如果你可以访问c++14,[](const auto&amp; pair),所以你不能忘记const KEY。

标签: c++ std


【解决方案1】:

当你迭代std::unordered_map&lt;Key, Value&gt;时,
你迭代std::pair&lt;const KEY, VALUE&gt;

在第二种情况下,您使用std::pair&lt;const KEY, VALUE&gt;&amp; 就可以了。 您甚至可以添加 const 因为您不更改该对:const std::pair&lt;const KEY, VALUE&gt;&amp;

在第一种情况下,您使用另一种类型std::pair&lt;KEY, VALUE&gt;&amp;std::pair&lt;KEY, VALUE&gt; 可以从 std::pair&lt;const KEY, VALUE&gt; 构造。但是,临时不能绑定到非常量左值引用。所以使用std::pair&lt;KEY, VALUE&gt;&amp; 是无效的。使用std::pair&lt;KEY, VALUE&gt; 是有效的,但会产生额外的副本。详情请见unexpected copies with foreach over a map

如果您可以访问 C++14,则可以使用通用 lambda 简化它:

[](const auto& p) {
    std::cout << p.first.posx << "+" << p.first.posy << "=" << p.second << "\n";
});

另外std::for_each也可以替换为基于范围的for循环(即使在C++11中):

for(const auto& p : sp) {
    std::cout << p.first.posx << "+" << p.first.posy << "=" << p.second << "\n";
};

【讨论】:

  • @MaxLanghof:在这种情况下,将for range 转换为for_each 也不难......
猜你喜欢
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 2021-09-03
相关资源
最近更新 更多