将从std::映射中获取的std::pair引用传递给接受std::对引用的函数


编辑:第一个问题的答案是使用std::pair。关于第二个问题(标记为"奖励问题"(有什么想法吗?

带有以下代码:

#include <map>
#include <vector>
void foo(std::pair<int, int>& p)  // EDIT: it needs to be non-const
{}
int main()
{
std::pair<int, int> p{1,2};
foo(p);
std::vector<std::pair<int, int>> v{{1,2}};
for (auto& element : v)
{
foo(element);  // works fine
}
std::map<int, int> m{std::make_pair(1,2)};
//std::map<int, int> m2{{1,2}};
for (auto& element : m)  // the problematic loop
{
foo(element);
}
return 0;
}

我得到以下消息,其中m在循环中:

错误:类型"std::pair&"的引用初始化无效从…起"std::pair"类型的表达式

和下面的m2:

错误:类型的非常量引用的初始化无效'std::对&'来自"std::pair"类型的右值

为什么?

额外的问题:我发现非常奇怪的是,当m2的初始化没有被注释掉,for循环保持不变(其中仍然有m,m2从未使用过(时,错误消息从更改

错误:类型"std::pair&"的引用初始化无效从…起"std::pair"类型的表达式

错误:类型的非常量引用的初始化无效'std::对&'来自"std::pair"类型的右值

我很想知道你对此的看法。我用onlinegdb.com 测试了这段代码

容器生成密钥const(这适用于所有关联容器(:

value_type    std::pair<const Key, T>

所以它应该是void foo(std::pair<int const, int>& p)

根据文档,

map::value_type = std::pair<const Key, T>

意思是

map<int,int>::value_type = pair<const int, int>

因此,编译器可以将pair<const int,int>&类型的元素隐式转换为pair<int,int>类型的临时(右值(,但这不能通过非常量引用传递给函数。

将参数类型更改为pair<const int,int>,或者按值取值。


作为参考,gcc 6.3提供了一个信息量很大的错误:

prog.cpp: In function ‘int main()’:
prog.cpp:21:13: error: invalid initialization of non-const reference of type ‘std::pair<int, int>&’ from an rvalue of type ‘std::pair<int, int>’
foo(element);
^~~~~~~
In file included from /usr/include/c++/6/bits/stl_algobase.h:64:0,
from /usr/include/c++/6/bits/stl_tree.h:63,
from /usr/include/c++/6/map:60,
from prog.cpp:1:
/usr/include/c++/6/bits/stl_pair.h:272:19: note:   after user-defined conversion: constexpr std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = const int; _U2 = int; typename std::enable_if<(std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_ConstructiblePair<_U1, _U2>() && std::_PCC<((! std::is_same<_T1, _U1>::value) || (! std::is_same<_T2, _U2>::value)), _T1, _T2>::_ImplicitlyConvertiblePair<_U1, _U2>()), bool>::type <anonymous> = 1u; _T1 = int; _T2 = int]
constexpr pair(const pair<_U1, _U2>& __p)
^~~~
prog.cpp:4:6: note:   initializing argument 1 of ‘void foo(std::pair<int, int>&)’
void foo(std::pair<int, int>& p)

特别要注意用户定义转换后的强烈线索。。。

您不允许修改地图的键,因此这是有效的:

#include <map>
#include <vector>
// foo can modify the first value of the pair
void foo(std::pair<int, int>& p)
{}
// fooConstFirst cannot modify the first value of the pair
void fooConstFirst(std::pair<const int, int>& p)
{}
int main()
{
std::pair<int, int> p{1,2};
foo(p);
std::vector<std::pair<int, int>> v{{1,2}};
for (auto& element : v)
{
foo(element);
}
std::map<int, int> m{std::make_pair(1,2)};
for (auto& element : m)
{
fooConstFirst(element);
}
return 0;
}

最新更新