编辑:第一个问题的答案是使用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;
}
我在后面的for循环中收到带有m的以下消息:
错误:来自“ std :: pair&”类型的引用的无效初始化 'std :: pair'类型的表达式
,然后在该位置加上m2:
错误:类型的非常量引用无效的初始化 类型为“ std :: pair”的右值中的“ std :: pair&”
那是为什么?
奖励问题: 我发现非常奇怪的是,当未注释掉m2的初始化并且for循环保持不变(仍然有m且从未使用过m2)时,错误消息将从
更改错误:来自“ std :: pair&”类型的引用的无效初始化 'std :: pair'类型的表达式
到
错误:类型的非常量引用无效的初始化 类型为“ std :: pair”的右值中的“ std :: pair&”
我很想知道你对此的想法。我用onlinegdb.com测试了这段代码
答案 0 :(得分:6)
The container makes the key const
(这适用于所有关联容器):
value_type std::pair<const Key, T>
因此它应该是void foo(std::pair<int const, int>& p)
。
答案 1 :(得分:4)
map::value_type = std::pair<const Key, T>
含义
map<int,int>::value_type = pair<const int, int>
因此,编译器可以将pair<const int,int>&
类型的元素隐式转换为pair<int,int>
类型的临时(右值),但这不能由非const ref传递给该函数。
将参数类型更改为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)
请特别注意有关用户定义转换后的强大线索 ...
答案 2 :(得分:3)
您不允许修改地图的键,因此可以:
#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;
}