当前位置: 首页 > 知识库问答 >
问题:

将“const std::map”作为“this”参数传递会丢弃lambda函数中的限定符[-fppermissive]

苏宏逸
2023-03-14

下面是一个基本的代码片段,我得到了一个错误:

错误:传递'constd::map

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的情况下删除点,但上面的代码片段只是一个更大问题的示例。

我检查了一些关于类似错误的问题:

  1. 错误:传递constd::映射

但在这两种情况下,都是因为std::map被声明为const。另一方面,我试图使用/访问的映射未声明为const,我的错误也与lambda有关。如您所见,我正在lambda捕获列表中创建原始my_map的副本,即map_lambda=my_map。那么,为什么我会得到这个-fpermissive错误?或者,当我们在lambda中捕获某个东西时,它是否会自动转换为常量

详细错误消息:

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)
       ^~~~~~~~

另一方面,我知道操作符[]如果键已经存在,则返回值,否则它会创建一个新键并插入值(并返回)。但是为什么std::map::operator[]const会给出编译错误?它不应该更像一个运行时错误吗?


共有2个答案

顾曾笑
2023-03-14

问题是该语句中使用的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\u lambda被视为一个常量对象。但是下标操作符要求对象是可修改的。也就是说,不能对类模板的常量对象使用下标运算符std::map

您应该将map_lambda声明为对my_map的非常量引用。

这就是改变lambda的方式

[&map_lambda = my_map] (const Point pt) -> bool {
        return map_lambda[pt.id];
    }
狄玉书
2023-03-14

lambda捕获的所有变量都是隐式的常量,除非将lambda标记为可变。map的操作符[]没有常量重载,因为它可能总是更改map(创建新的键值对)。

如果您确定每个pt。id存在于地图中,请将操作符[]更改为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];
}
 类似资料:
  • 错误:将“const A”作为“void A::hi()”的“this”参数传递会丢弃限定符[-fppermissive] 我不明白为什么会出现这个错误,我没有返回任何东西,只是传递了对象的引用,就是这样。 编辑 我用const correction修复了它,但是现在我试图在同一个方法中调用方法,我得到了同样的错误,但奇怪的是我没有传递这个方法的引用。 错误:将“const A”作为“void A

  • 在gcc 5.4.0上,从const C std::map获取条目时无法编译。 这看起来类似于传递“const”。此参数丢弃限定符[-fppermissive],它是关于

  • 我有与这里、这里或这里相同的问题,除了我为参数和函数设置了const: 但我有同样的编译错误:

  • 我将对象的引用传递给函数,并使用const表示它是只读方法,但如果我在该方法中调用另一个方法,即使我没有将引用作为参数传递,也会发生此错误。 错误:将'const A'传递为'valA::hello()'的'this'参数会丢弃限定符[-fpermissive] 错误:将“const A”作为“void A::world()”的“this”参数传递将丢弃限定符[-fpermissive]

  • 我有一个类缓存,它的函数write指定为 我这样调用这个函数。 上面的一行给了我以下错误 将“const Cache”作为“bool Cache::write(const MemoryAccess)”的“this”参数传递 this参数是特定于编译器的,它有助于代码混乱和中断本地命名空间变量优先级。但这样的变量并没有在这里传递。

  • 代码如下(为简洁起见摘录): 颜色h: 颜色cpp: 我得到以下错误: 颜色cpp:16:29:错误:传递“const std::map” 错误指的是“返回颜色[cColortype];”在getColorText中。 我写这篇文章是为了一个类项目,我可以通过删除getColorText签名中的const声明来让它工作,但我正在尝试学习/采用良好的实践,并遵循建议,在不修改数据的成员函数中使用co