将“const std::map<int, bool>”作为“this”参数传递会丢弃 lambda 函数中的限定符 [-fpermissive]
Posted
技术标签:
【中文标题】将“const std::map<int, bool>”作为“this”参数传递会丢弃 lambda 函数中的限定符 [-fpermissive]【英文标题】:Getting passing ‘const std::map<int, bool>’ as ‘this’ argument discards qualifiers [-fpermissive] in lambda function 【发布时间】:2021-07-23 06:54:14 【问题描述】:这是我收到错误的基本代码 sn-p:
错误:将“const std::map
”作为“this”参数传递会丢弃限定符 [-fpermissive]`
struct Point
float x;
float y;
int id;
Point(float x, float y, float id) : x(x), y(y), id(id)
;
void removePoints(std::vector<Point> &points_vec)
std::map<int, bool> my_map;
for (const auto& pt : points_vec)
if(pt.id < 0)
my_map[pt.id] = true;
else
my_map[pt.id] = false;
points_vec.erase(std::remove_if(points_vec.begin(), points_vec.end(), [map_lambda = my_map] (const Point pt) -> bool
return map_lambda[pt.id];
), points_vec.end());
int main(int argc, char const *argv[])
std::vector<Point> points_vec;
points_vec.push_back(Point(1, 2, 0));
points_vec.push_back(Point(1, 5, -1));
points_vec.push_back(Point(3, 3, -1));
points_vec.push_back(Point(4, 9, 2));
points_vec.push_back(Point(0, 1, 3));
points_vec.push_back(Point(-1, 7, -2));
std::cout << points_vec.size() << std::endl;
removePoints(points_vec);
std::cout << points_vec.size() << std::endl;
return 0;
注意:我知道我可以不使用std::map
删除点,但上面的代码 sn-p 只是一个更大问题的示例。
我检查了一些关于类似错误的问题:
-
error: passing ‘const std::map<int, int>’ as ‘this’ argument discards qualifiers [-fpermissive]
C++ "error: passing 'const std::map<int, std::basic_string<char> >' as 'this' argument of ..."
但在他们两个中,这是因为std::map
已被声明为const
。另一方面,我尝试使用/访问的map
尚未声明为const
,我的错误也与lambda 有关。如您所见,我在 lambda 捕获列表中将原始 my_map
的副本创建为 map_lambda = my_map
。那么,为什么我会收到这个 -fpermissive
错误?或者,当我们在 lambda 中捕获某些内容时,它是否会自动转换为 const
?
详细的错误信息:
main.cpp: In lambda function:
main.cpp:26:32: error: passing ‘const std::map<int, bool>’ as ‘this’ argument discards qualifiers [-fpermissive]
return map_lambda[pt.id];
^
In file included from /usr/include/c++/7/map:61:0,
from main.cpp:2:
/usr/include/c++/7/bits/stl_map.h:484:7: note: in call to ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = bool; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, bool> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = bool; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’
operator[](const key_type& __k)
^~~~~~~~
顺便说一句,我知道operator[]
如果键已经存在则返回值,否则它会创建一个新键并插入值(并返回它)。但是为什么const
for std::map::operator[]
会出现编译错误呢?它不应该更像是运行时错误吗?
【问题讨论】:
【参考方案1】:所有由 lambda 捕获的变量都是隐式的 const
,除非你将 lambda 标记为 mutable
。 operator[]
的 map 没有 const
重载,因为它可能总是会更改 map(创建新的键值对)。
如果您确定地图中存在每个pt.id
,请将operator []
更改为at()
调用:
[map_lambda = my_map] (const Point pt) -> bool
return map_lambda.at(pt.id);
如果您想在地图中创建不存在的键,请将 lambda 更改为 mutable
:
[map_lambda = my_map] (const Point pt) mutable -> bool
return map_lambda[pt.id];
【讨论】:
请注意,在[map_lambda = my_map]
中,map_lambda
将是my_map
的副本,因此无论发生什么,my_map
都不会以任何方式改变到map_lambda
。如果您需要更新my_map
,请改为通过引用来捕获它,例如[&map_lambda = my_map]
,或者甚至只是[&my_map]
或[&]
,因为在此示例中它实际上不需要单独的名称。
@RemyLebeau 感谢您提供这些提示 :) 只是为了确认,除了通过引用捕获 my_map
之外,我还必须将 lambda 更改为 mutable
,对吗?因为,正如上面提到的@Yksisarvinen,没有mutable
,它会想要const
参考,对吧?如果我错了,请纠正我。谢谢!
@Milan "我还必须将 lambda 更改为 mutable
,对吗?" - 是的,您需要 mutable
,否则 my_map
将被捕获const
引用,从而阻止使用 map::operator[]
。
@Milan “这不应该是运行时错误吗?” - 不。允许在 const
对象上调用非常量方法是没有意义的。并且operator[]
必须是非常量的,因此它可以改变map
的内容。这只是 C++ 中 const-correctness 工作原理的一部分
让我们continue this discussion in chat。【参考方案2】:
问题在于该语句中使用的 lambda 表达式
points_vec.erase(std::remove_if(points_vec.begin(), points_vec.end(), [map_lambda = my_map] (const Point pt) -> bool
return map_lambda[pt.id];
), points_vec.end());
是不可变的。所以map_lambda
被认为是一个常量对象。但是下标运算符要求对象是可修改的。那就是你不能将下标运算符与类模板std::map
的常量对象一起使用。
您应该将map_lambda
声明为对my_map
的非常量引用。
那就是像改变 lambda 一样
[&map_lambda = my_map] (const Point pt) -> bool
return map_lambda[pt.id];
【讨论】:
感谢来自莫斯科的@Vlad 的回答...但正如@Yksisarvinen 上面指出的那样,除非我使用mutable
,否则在lambda 中捕获的任何内容都会隐式转换为const
,对吗?那么,这不是const
参考吗?如果我错了,请纠正我。再次感谢!
@Milan 我展示了如何在 lambda 中声明对原始地图的非常量引用。
感谢您的回复,但如果没有mutable
,[&map_lambda = my_map]
不会是const
的参考吗?抱歉,但现在我有点困惑,因为正如@Remy Lebeau 指出的那样,我需要mutable
,否则它将是const
参考!
@Milan 不,不会。成为一个恒定的参考
谢谢@Vlad,我试过你说的,看起来如果我在捕获列表中使用引用,那么即使没有mutable
,我也无法修改捕获的对象。所以,只是为了确认,mutable
只有当我按价值捕获某些东西时才会出现,对吧?如果我错了,请纠正我。再次感谢:)以上是关于将“const std::map<int, bool>”作为“this”参数传递会丢弃 lambda 函数中的限定符 [-fpermissive]的主要内容,如果未能解决你的问题,请参考以下文章
Javascript 将正则表达式 \\n 替换为 \n,将 \\t 替换为 \t,将 \\r 替换为 \r 等等